jwt 認證規則


jwt 認證規則:

介紹:

jwt: json web token
優點:
    1)數據庫不需要存儲token,所以服務器的 IO 操作會減少(沒有IO寫操作)
    2)客戶端存Token,服務器只存儲簽發與校驗算法,執行效率高
    3)簽發與校驗算法在多個服務器上可以直接統一,所以jwt認證規則下,服務器做集群非常便捷

    
突破點:
    1)token必須要有多個部分組成,有能反解的部分,也要有不能反解的部分 - jwt采用的都是三段式
    2)token中必須包含過期時間,保證token的安全性與時效性

jwt原理:
    1)jwt由 頭.載荷.簽名 三部分組成
    2)每一部分數據都是一個json字典,頭和載荷采用 base64 可逆加密算法加密,簽名采用 HS256 不可逆加密


內容:

內容:
1)頭(基本信息):可逆不可逆采用的加密算法、公司名稱、項目組信息、開發者信息...
{
	"company": "小女孩",
	...
}
2)載荷(核心信息):用戶主鍵、用戶賬號、客戶端設備信息、過期時間...
{
	'pk': 1,
	...
}
3)簽名(安全信息):頭的加密結果、載荷的加密結果、服務器的安全碼(鹽)...
{
	"header": "..."
	...
    #每一個 django 的鹽:settings.py
    SECRET_KEY = '2w$ejiavxdjwbz_x9)!31^kvc1hku)=h7-bdv^f)ub!4d712*e'
}

核心算法:

簽發算法:

簽發算法:

1)頭內容寫死(可以為空{}):公司、項目組信息都是固定不變的
	=> 將數據字典轉化成json字符串,再將json字符串加密成base64字符串
	
2)載荷的內容:用戶賬號、客戶端設備信息是由客戶端提供,用戶主鍵是客戶端提供賬號密碼校驗User表通過后才能確定,過期時間根據當前時間與配置的過期時間相結合產生
	=> 將數據字典轉化成json字符串,再將json字符串加密成base64字符串
	
3)簽名的內容,先將頭的加密結果,載荷的加密結果作為成員,再從服務器上拿安全碼(不能讓任何客戶端知道),也可以額外包含載荷的部分(用戶信息,設備信息)
	=> 將數據字典轉化成json字符串,再將json字符串不可逆加密成HS256字符串
	
4)將三個字符串用 . 連接產生三段式token

校驗算法:

1)從客戶端提交的請求中拿到token,用 . 分割成三段(如果不是三段,非法)
2)頭(第一段)可以不用解密
3)載荷(第二段)一定需要解密,先base64解密成json字符串,再轉換成json字典數據
	i)用戶主鍵與用戶賬號查詢User表確定用戶是否存在
	ii)設備信息用本次請求提交的設備信息比對,確定前后是否是同一設備,決定是否對用戶做安全提示(eg:短信郵箱提示異地登錄)(同樣的安全保障還可以為IP、登錄地點等)
	iii)過期時間與當前時間比對,該token是否在有效時間內
4)簽名(第三段)采用加密碰撞校驗
	i)將頭、載荷加密字符串和數據庫安全碼形成json字典,轉換成json字符串
	ii)采用不可逆HS256加密形成加密字符串
	iii)新的加密字符串與第三段簽名碰撞比對,一致才能確保token是合法的
	
5)前方算法都通過后,載荷校驗得到的User對象,就是該token代表的登錄用戶(Django項目一般都會把登錄用戶存放在request.user中)

刷新算法:

    1)要在簽發token的載荷中,額外添加兩個時間信息:第一次簽發token的時間,最多往后刷新的有效時間
    
    2)每一請求攜帶token,不僅走校驗算法驗證token是否合法,還要額外請求刷新token的接口,完成token的刷新:校驗規則與校驗算法差不多,但是要將過期時間后移(沒有超過有效時間,產生新token給客戶端,如果超過了,刷新失敗)
    3)所以服務器不僅要配置過期時間,還需要配置最長刷新時間

django-rest-framework-jwt

REST框架JWT Auth 模塊

使用pip... 安裝

$ pip install djangorestframework-jwt

本質:(源碼)--ObtainJSONWebToken
	 def validate(self, attrs):
        token = attrs['token']

        payload = self._check_payload(token=token)
        user = self._check_user(payload=payload)

        return {
            'token': token,
            'user': user
        }
1._check_payload 方法 (源碼解析)
2._check_user    方法

自定義配置:

# drf-jwt自定義配置
import datetime
JWT_AUTH = {
    # 過期時間
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
    # 是否允許刷新
    'JWT_ALLOW_REFRESH': True,
    # 最大刷新的過期時間
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}

模塊的使用:

#子路由: urls.py

from django.conf.urls import url, include
from . import views

from .router import router
# eg: router.register('users', UserModelViewSet, basename='user')

from rest_framework_jwt.views import ObtainJSONWebToken, obtain_jwt_token, refresh_jwt_token, verify_jwt_token
urlpatterns = [
    # url(r'^login/$', ObtainJSONWebToken.as_view()),
    url(r'^login/$', obtain_jwt_token),
    url(r'^refresh/$', refresh_jwt_token),
    url(r'^verify/$', verify_jwt_token),

    url(r'', include(router.urls))
]

# 發送的請求方式: post

_check_payload 方法 :

    def _check_payload(self, token):
        # Check payload valid (based off of JSONWebTokenAuthentication,
        # may want to refactor)
        try:
            payload = jwt_decode_handler(token)
        except jwt.ExpiredSignature:
            msg = _('Signature has expired.')
            raise serializers.ValidationError(msg)
        except jwt.DecodeError:
            msg = _('Error decoding signature.')
            raise serializers.ValidationError(msg)

        return payload

_check_user 方法:

 def _check_user(self, payload):
        username = jwt_get_username_from_payload(payload)

        if not username:
            msg = _('Invalid payload.')
            raise serializers.ValidationError(msg)

        # Make sure user exists
        try:
            user = User.objects.get_by_natural_key(username)
        except User.DoesNotExist:
            msg = _("User doesn't exist.")
            raise serializers.ValidationError(msg)

        if not user.is_active:
            msg = _('User account is disabled.')
            raise serializers.ValidationError(msg)

        return user


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM