iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Modern Web

Vue+Django+MongoDB+Nginx 全端開發系列 第 17

Json web token authentication --part2: Django

  • 分享至 

  • xImage
  •  

django 這邊需要使用 Django REST framework (drf) 及 drf 官方推薦實作 JWT 的 Django-rest-framework-simplejwt 這兩個套件。

pip install djangorestframework djangorestframework_simplejwt

settings.py

再來設定 django 的 back_end/settings.py 引入,首先來設定 INSTALLED_APPS ,將 rest_frameworkrest_framework_simplejwt.token_blacklist 引入

INSTALLED_APPS = [
    'rest_framework',
    'rest_framework_simplejwt.token_blacklist'
]

加入這段 REST_FRAMEWORK

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}

再來要把 JWT 的設定改成自己喜歡的樣子,先引入 timedelta

from datetime import timedelta

設定 ACCESS_TOKEN_LIFETIME 時效比較短, REFRESH_TOKEN_LIFETIME 時效比較長,原則上是看你想要 user 維持登入時間多久,不過接下來設定 ROTATE_REFRESH_TOKENS 等於 True,官方預設更新 token 的時候,只更新 access token,只回傳 access token,所以使用者最多只能維持登入 30 天,這邊改成 True,會連 refresh token 一起更新,之後每次 refresh , server 都會回傳一組 access 和 refresh token 給前台,再配合 BLACKLIST_AFTER_ROTATION 為 True,會讓 token 刷新之後,舊的 refresh 和 access token 都失去權限,這樣別人就不能舊的 refresh token 去獲得新的 token,會更加安全。詳細內容可以看一下官方的 settings 說明。

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': True,
    'UPDATE_LAST_LOGIN': False,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': None,
    'ISSUER': None,
    'JWK_URL': None,
    'LEEWAY': 0,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'USER_AUTHENTICATION_RULE':  'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}

https://ithelp.ithome.com.tw/upload/images/20220914/20132990tzn4Ga0nJK.png

authentication

我們先來做一個用來做驗證相關的 module

python manage.py startapp authentication

加入 app

INSTALLED_APPS = [
    'authentication'
]

加入 url

urlpatterns = [
    path('api/',include('authentication.urls'))
]

新增 urls.pyback_end/authentication ,refresh 和 verify 功能我們用 simple jwt 內建的方法

# back_end/authentication/urls.py
from django.urls import path
from . import views
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
    TokenVerifyView
)

urlpatterns = [
    # JWT ###################################
    path('token/', views.MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]

至於獲取 token,如果在前台解析 token,可以獲得一些 payload 資訊,不過預設只有這些簡單的資訊,至少回個 username 吧!不然超難用的誒

https://ithelp.ithome.com.tw/upload/images/20220914/20132990YTOVDMeAWg.png

所以我們來 back_end/authentication/views.py 來客製化我們獲取 token 的方法,這裡我們多加入 username 資訊,這裡基本上就是照抄官方 document 的客製化方法

from django.shortcuts import render

# Create your views here.

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)

        # Add custom claims
        token['username'] = user.username

        return token

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

後端基本上到這裡,下一篇來講前端該怎麼搞。


上一篇
Json web token authentication --part1: JWT introduction
下一篇
Json web token authentication --part3: Vue
系列文
Vue+Django+MongoDB+Nginx 全端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言