1、工作原理
""" 1) jwt = base64(頭部).base(載荷 payload).hash256(base64(頭部).base(載荷).金鑰) 2) base64是可逆的演算法、hash256是不可逆的演算法 3) 金鑰是固定的字串,儲存在伺服器 """
2、drf-jwt
官網
http://getblimp.github.io/django-rest-framework-jwt/
安裝子:虛擬環境
pip install djangorestframework-jwt
使用:user/urls.py
from django.urls import path from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ path('login/', obtain_jwt_token), ]
測試介面:post請求
""" postman發生post請求 介面:http://api.luffy.cn:8000/user/login/ 資料: { "username":"admin", "password":"admin" } """
3、drf-jwt開發
配置資訊:JWT_AUTH到dev.py中
import datetime JWT_AUTH = { # 過期時間 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # 自定義認證結果:見下方序列化user和自定義response 'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler', }
序列化user:user/serializers.py(自己建立)
from rest_framework import serializers from . import models class UserModelSerializers(serializers.ModelSerializer): class Meta: model = models.User fields = ['username']
自定義response:user/utils.py
from .serializers import UserModelSerializers def jwt_response_payload_handler(token, user=None, request=None): return { 'status': 0, 'msg': 'ok', 'data': { 'token': token, 'user': UserModelSerializers(user).data } }
基於drf-jwt的全域性認證:user/authentications.py(自己建立)
import jwt from rest_framework.exceptions import AuthenticationFailed from rest_framework_jwt.authentication import jwt_decode_handler from rest_framework_jwt.authentication import get_authorization_header from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): jwt_value = get_authorization_header(request) if not jwt_value: raise AuthenticationFailed('Authorization 欄位是必須的') try: payload = jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: raise AuthenticationFailed('簽名過期') except jwt.InvalidTokenError: raise AuthenticationFailed('非法使用者') user = self.authenticate_credentials(payload) return user, jwt_value
解讀:
JSONWebTokenAuthentication 是一個自定義身份驗證類,它通常用於 Django REST framework 中實現
基於 JSON Web Token (JWT) 的使用者認證。
這個類繼承自 BaseJSONWebTokenAuthentication,並覆蓋了 authenticate 方法以處理 JWT 的驗證邏輯。 在該方法中: 透過 get_authorization_header(request) 函式從請求的頭部(通常是 'Authorization' 欄位)獲取 JWT 值。 如果沒有找到 JWT 值,則丟擲 AuthenticationFailed 異常,提示 "Authorization 欄位是必須的"。 嘗試使用 jwt_decode_handler(jwt_value) 解碼提供的 JWT。這個解碼函式會檢查簽名的有效性和 token 是否過期等。 如果簽名已過期,會丟擲 ExpiredSignature 異常,此時捕獲異常並丟擲 AuthenticationFailed,提示 "簽名過期"。 如果 JWT 校驗失敗(比如 token 格式錯誤、金鑰不匹配或其他任何無效情況),會丟擲 InvalidTokenError 異常,
此時也會捕獲異常並丟擲 AuthenticationFailed,提示 "非法使用者"。 如果 JWT 解碼成功,呼叫 self.authenticate_credentials(payload) 來進一步驗證 payload 中攜帶的使用者憑證資訊是否有效,
並據此獲取或建立對應的使用者物件。 如果使用者憑證驗證成功,返回一個包含使用者物件和原始 JWT 值的元組 (user, jwt_value)。這樣,經過此身份驗證流程後,
合法的使用者就能透過 JWT 進行後續的 API 請求授權訪問。
全域性啟用:settings/dev.py
REST_FRAMEWORK = { # 認證模組 'DEFAULT_AUTHENTICATION_CLASSES': ( 'user.authentications.JSONWebTokenAuthentication', ), }
區域性啟用禁用:任何一個cbv類首行
# 區域性禁用 authentication_classes = [] # 區域性啟用 from user.authentications import JSONWebTokenAuthentication authentication_classes = [JSONWebTokenAuthentication]
多方式登入:user/utils.py
import re from .models import User from django.contrib.auth.backends import ModelBackend class JWTModelBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: if re.match(r'^1[3-9]\d{9}$', username): user = User.objects.get(mobile=username) else: user = User.objects.get(username=username) except User.DoesNotExist: return None if user.check_password(password) and self.user_can_authenticate(user): return user
配置多方式登入:settings/dev.py
AUTHENTICATION_BACKENDS = ['user.utils.JWTModelBackend']
手動簽發JWT:瞭解 - 可以擁有原生登入基於Model類user物件簽發JWT
from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload)