JWT實現過程及應用

bajie_new發表於2020-10-31

jwt實現過

# 使用者登入,返回給客戶端token(服務端不儲存),使用者帶著token,服務端拿到token再校驗;

1,提交使用者名稱和密碼給服務端,如果登陸成功,jwt會建立一個token,並返回;
	第一段:header,內部包含 (演算法/token型別)
        {
            "typ": "JWT",    # 宣告型別為jwt
            "alg": "HS256"   # 宣告簽名演算法為SHA256
        }
        # json轉化字串做base64url加密,可反解
    第二段:payload,包含(標準中註冊的宣告、公共宣告、私有宣告(使用者資訊))
        {  # 私有聲名
            “id”: “12”,
            “name”: “bajie″,
            “exp”: 60        # 超時時間
        }
        # 公共宣告:公共的宣告可以新增任何的資訊,一般新增使用者的相關資訊或其他業務需要的必要資訊.
        """ 註冊的宣告
            iss: jwt簽發者
            sub: jwt所面向的使用者
            aud: 接收jwt的一方
            exp: jwt的過期時間,這個過期時間必須要大於簽發時間
            nbf: 定義在什麼時間之前,該jwt都是不可用的.
            iat: jwt的簽發時間
            jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
		"""
        # json轉化字串做base64url加密,可反解
    第三段:
        1,將第一段和第二段的密文拼接
        2,HS256加密 + 加鹽
        3,對HS256加密後的密文再用 base64url 加密
2,使用者訪問,需要攜帶token,後端進行校驗
    1,獲取token
    2,切割,對第二段解密,獲取payload資訊,檢測是否超時
    3,把第一段和第二段的密文拼接,再次執行HS256加密 + 加鹽   得到  密文
    4,密文 == token 匹配   (如果修改超時時間 則不通過)

  

jwt簡單應用

安裝: pip install pyjwt
    
import jwt
import datetime
from rest_framework.views import APIView
from rest_framework.response import Response
from jwt import exceptions

from api import models


class LoginAPIview(APIView):
    def get(self, request, *args, **kwargs):
        # 鹽
        sail = "sadjmasklfn63a5s62dwa@ddas/352asdfa"
        """
            1,獲取token
            2,切割,對第二段解密,獲取payload資訊,檢測是否超時
            3,把第一段和第二段的密文拼接,再次執行HS256加密 + 加鹽   得到  密文
            4,密文 == token 匹配   (如果修改超時時間 則不通過)
        """
        token = request.query_params.get("token")
        verified_payload = None
        msg = ''
        try:
            # 反解出來的第二段資料
            verified_payload = jwt.decode(token, sail, True)
        except exceptions.ExpiredSignatureError:  # 超時
            msg = "token失效"
        except jwt.DecodeError:
            msg = "token認證失敗"
        except jwt.InvalidTokenError:
            msg = "非法token"

        if not verified_payload:
            return Response({'code': '登入失敗', "error": msg})
        # print(verified_payload["id"],verified_payload["username"])
        return Response({"ok": "登陸成功"})

    def post(self, request, *args, **kwargs):
        user = request.data.get('username')
        pswd = request.data.get('password')
        obj = models.UserInfo.objects.filter(username=user, password=pswd).first()
        if obj:
            # 鹽
            sail = "sadjmasklfn63a5s62dwa@ddas/352asdfa"
            # 構造 第一段: header, 內部包含(演算法 / token型別)  預設
            headers = {
                "typ": "JWT",  # 宣告型別為jwt
                "alg": "HS256"  # 宣告簽名演算法為SHA256
            }
            # 第二段: payload, 包含(標準中註冊的宣告、公共宣告、私有宣告(使用者資訊))
            payload = {  # 私有聲名
                'id': obj.id,
                'username': obj.username,
                'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=1)  # 超時時間1分鐘
            }
            res_token = jwt.encode(headers=headers, payload=payload, key=sail, algorithm='HS256').decode('utf-8')
            return Response({"msg": "登入成功", "token": res_token})

        return Response("0")

  

相關文章