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('账户不存在!')
逻辑是从上往下走的,所以在还没有返回数据之前,写在哪里都是可以的.