drf—— JWT認證及基本使用

1、JWT認證介紹

1 再也不使用Session認證機制,而使用Json Web Token(本質就是token)認證機制,用戶登陸認證
2 用戶只要登陸了,返回用戶一個token串(隨機字符串),每次用戶發請求,須要攜帶這個串過來,驗證經過,咱們認爲用戶登陸了
3 JWT的構成(字符串)
    -三部分(每一部分中間經過.分割):header   payload  signature
    -header:聲明類型,這裏是jwt,聲明加密算法,頭裏加入公司信息...,用base64轉碼
        {
          'typ': 'JWT',
          'alg': 'HS256' #用md5也行
        }
    -payload:荷載(有用),當前用戶的信息(用戶名,id,這個token的過時時間,手機號),用base64轉碼
        {
          "sub": "1234567898",
          "name": "egon",
          "admin": true,
          "userid":1,
          'mobile':123444444
        }
    -signature:簽名
        -把前面兩部分的內容經過加密算法+密鑰加密後獲得的一個字符串
        
        
    -jwt總的構成樣子:
      eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
        
4 JWT認證原理
    -用戶攜帶用戶名,密碼登陸個人系統,校驗經過,生成一個token(三部分),返回給用戶---》登陸功能完成
    -訪問須要登陸的接口(用戶中心),必須攜帶token過來,後端拿到token後,把header和payload截出來,再經過同樣的加密方式和密碼獲得一個signature,
    和該token的signature比較,若是同樣,表示是正常的token,就能夠繼續日後訪問

2、jwt基本使用(使用內置jwt

安裝前端

1 drf中使用jwt,藉助第三方https://github.com/jpadilla/django-rest-framework-jwt
2 安裝 pip3 install djangorestframework-jwt

快速使用git

3 快速使用(默認使用auth的user表)
    (1) 在默認auth的user表中建立一個用戶
    (2) 在路由中配置
    from rest_framework_jwt.views import obtain_jwt_token
        path('login/', obtain_jwt_token),
    (3) 用postman向這個地址發送post請求,攜帶用戶名,密碼,登錄成功就會返回token
    
    (4)obtain_jwt_token本質也是一個視圖類,繼承了APIView
        -經過前端傳入的用戶名密碼,校驗用戶,若是校驗經過,生成token,返回
        -若是校驗失敗,返回錯誤信息
    訪問地址:http://127.0.0.1:8000/homework/login/

用戶登陸之後才能訪問某個接口github

4 用戶登陸之後才能訪問某個接口
    -jwt模塊內置了認證類,拿過來局部配置就能夠
    -class OrderView(APIView):
        # 只配它不行,無論是否登陸,都能範圍,須要搭配一個內置權限類
        authentication_classes = [JSONWebTokenAuthentication, ]
        permission_classes = [IsAuthenticated,]
        def get(self, request):
            print(request.user.username)
            return Response('訂單的數據')
   訪問地址: http://127.0.0.1:8000/homework/order/  
注意:訪問的時候須要在header內攜帶jwt

用戶未登陸,能夠訪問算法

5 用戶未登陸,能夠訪問
    -class OrderView(APIView):
        # 只配它不行,無論是否登陸,都能範圍,須要搭配一個內置權限類
        authentication_classes = [JSONWebTokenAuthentication, ]
        def get(self, request):
            print(request.user.username)
            return Response('訂單的數據')
   訪問地址: http://127.0.0.1:8000/homework/order/

注意事項django

6 若是用戶攜帶了token,而且配置了JSONWebTokenAuthentication,從request.user就能拿到當前登陸用戶,若是沒有攜帶,當前登陸用戶就是匿名用戶

7 前端要發送請求,攜帶jwt,格式必須以下
    -把token放到請求頭header中,key爲:Authorization 
    -value必須爲:jwt eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6ImVnb24xIiwiZXhwIjoxNjA1MjQxMDQzLCJlbWFpbCI6IiJ9.7Y3PQM0imuSBc8CUe_h-Oj-2stdyzXb_U-TEw-F82WE

3、控制登陸接口返回的數據格式

1 控制登陸接口返回的數據格式以下
    {
    code:100
    msg:登陸成功
    token:asdfasfd
    username:egon
    }
    
2 寫一個函數utils.py
    from homework.serializer import UserReadOnlyModelSerializer
    def jwt_response_payload_handler(token, user=None, request=None):
        return {'code': 100, 
                'msg': '登陸成功',
                'token': token,
                'user': UserReadOnlyModelSerializer(instance=user).data
                }
3 在setting.py中配置
    import datetime
    JWT_AUTH = {
        'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',
    }

4、自定義基於jwt的認證類

1 本身實現基於jwt的認證類,經過認證,才能繼續訪問,通不過認證就返回錯誤
2 本身寫個類auth.py class JwtAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): # 認證邏輯() # token信息能夠放在請求頭中,請求地址中 # key值能夠隨意叫 # token=request.GET.get('token') token=request.META.get('HTTP_Authorization'.upper()) # 校驗token是否合法 try: payload = jwt_decode_handler(token) except jwt.ExpiredSignature: raise AuthenticationFailed('過時了') except jwt.DecodeError: raise AuthenticationFailed('解碼錯誤') except jwt.InvalidTokenError: raise AuthenticationFailed('不合法的token') user=self.authenticate_credentials(payload) return (user, token)
3 在視圖類中配置 authentication_classes = [JwtAuthentication, ] # 視圖views.py全代碼: from app01.auth import JwtAuthentication   class OrderView(APIView): # 登陸之後才能訪問   authentication_classes = [JwtAuthentication, ]   def get(self, request):   print(request.user.username)    return Response('訂單的數據')
相關文章
相關標籤/搜索