drf-rest_framework-jwt相關
阿新 • • 發佈:2020-07-15
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('賬戶不存在!')
邏輯是從上往下走的,所以在還沒有返回資料之前,寫在哪裡都是可以的.