drf—— JWT認證及基本使用


一、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,就可以繼續往后訪問

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

安裝

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

快速使用

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/

用戶登錄以后才能訪問某個接口

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/

注意事項

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

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

三、控制登錄接口返回的數據格式

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',
    }

四、自定義基於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('訂單的數據')

 


免責聲明!

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



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