1. 程式人生 > 實用技巧 >drf-rest_framework-jwt相關

drf-rest_framework-jwt相關

1.安裝

pip install djangorestframework-jwt

2.建立超級使用者,一步一步往填寫,賬戶,密碼,確認密碼,若是弱密碼,會問你"密碼很弱,希望繼續使用嗎?(Y/N)",肯定是輸入y繼續

3.然後就可以利用後臺進行普通,或者其他使用者的建立等操作了

4.配置路由urls.py檔案

from app_jwt import views
from django.urls import path, re_path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path(
'login/', obtain_jwt_token), ]

這裡我使用了路由分發

進行postman訪問成功

若是使用自居帶的進行訪問的話要在頭上加點東西

傳送訪問請求(必須帶jwt空格)

配置檔案settings.py中書寫自己寫的自動簽發與過期時間等設定

import datetime

JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app_jwt.utils.my_jwt_response_payload_handler',  # 這裡的是我自己的app的檔案裡自己書寫的
    'JWT_EXPIRATION_DELTA
': datetime.timedelta(days=7), # 過期時間,手動配置 }
from app_jwt.utils import my_jwt_response_payload_handler # 用這句話的能保用 詞不會錯,因為在配置檔案中不會補全.
明顯 是 app_jwt專案 下面有個 utils.py檔案中 有個 類或者 方法叫
 my_jwt_response_payload_handler  我這裡是個方法

下面書寫自定義的檔案的程式碼
def my_jwt_response_payload_handler(token, user=None, request=None):
    
return { 'status': 100, 'msg': "ok", 'data': { 'token': token, } }
這裡的程式碼 是 自己寫返回些什麼內容 ,若是使用自帶的話就只會返回一個token

若是想要全域性認證的話自己寫一個認證類配置settings.py檔案

REST_FRAMEWORK = {
    # 認證模組
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'users.app_jwt.utils.MyJwt',
    ),
}

下面是我自己定義的認證類

from rest_framework_jwt.utils import jwt_decode_handler
from rest_framework_jwt.authentication import BaseAuthentication
import jwt
from rest_framework.exceptions import AuthenticationFailed
from api import models


class MyJwt(BaseAuthentication):
    def authenticate(self, request):
        jwt_value = request.META.get('HTTP_AUTHORIZATION')
        if jwt_value:
            try:
                payload = jwt_decode_handler(jwt_value)
            except jwt.ExpiredSignatureError:
                raise AuthenticationFailed('簽名過期!')
            except jwt.InvalidTokenError:
                raise AuthenticationFailed('使用者不合法!')
            except Exception as e:
                raise AuthenticationFailed(str(e))
            user = models.User.objects.get(pk=payload.get('user_id'), username=payload.get('username'))
            return user, jwt_value
        raise AuthenticationFailed('您未攜帶token認證資訊!')
from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from app_jwt import serializer
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated

from .utils import MyJwt


class GoodsAPIView(APIView):
    authentication_classes = [] # 配置了全域性的話,區域性禁用加上這句就可以了
    authentication_classes = [MyJwt] # 未配置全域性的話,區域性使用 加上這句 後面是自己定義的認證類
    permission_classes = [IsAuthenticated] # 都要配合許可權認證一塊兒使用

    def get(self, request, *args, **kwargs):
        return Response('good資訊!')

多方式登入,(使用者名稱/手機號/郵箱)

檢視檔案views.py

class LoginView(ViewSet):
    def login(self, request, *args, **kwargs):
        login_serializer = serializer.LoginModelSerializer(data=request.data)
        login_serializer.is_valid(raise_exception=True)
        token = login_serializer.context.get('token')
        return Response({'status': 200, 'msg': '登入成功!', 'token': token, })

序列化器serializer.py

class LoginModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = models.User
        fields = ['username', 'password']

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        elif re.match('^.*@.*$', username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()

        if user:
            if user.check_password(password):
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)
                self.context['token'] = token

                return attrs
            else:
                raise ValidationError('密碼錯誤!')
        else:
            raise ValidationError('賬戶不存在!')

路由檔案urls.py

from app_jwt import views
from django.urls import path, re_path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('login/', obtain_jwt_token),
    path('test/', views.TestAPIView.as_view()),
    path('goods/', views.GoodsAPIView.as_view()),
    #登入相關   
    path('login1/', views.LoginView.as_view({'post': 'login'})),
    path('login2/', views.Login2View.as_view({'post': 'login'})),



]

也可以把序列化器中的相關邏輯語句寫在檢視檔案中像這樣:

class Login2View(ViewSet):
    def login(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        elif re.match('^.*@.*$', username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()
        if user:
            if user.check_password(password):
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)
                return Response({'status': 200, 'msg': '登入成功!', 'token': token, })
            raise ValidationError('密碼錯誤 !')
        raise ValidationError('賬戶不存在!')

邏輯是從上往下走的,所以在還沒有返回資料之前,寫在哪裡都是可以的.