路由
# 127.0.0.1:8000/app01/api/v1/jwt/login/--->post请求
router.register('jwt', UserJWTView, 'jwt')
urlpatterns = [
# # 方案一: 前面可以再加前缀
path('api/v1/', include(router.urls)),
path('users/', UserView.as_view()),
path('login/', token_obtain_pair),
]
视图类
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from .serializer import LoginJWTSerializer
class UserJWTView(GenericViewSet):
serializer_class = LoginJWTSerializer
@action(methods=['POST'],detail=False)
def login(self,request,*args,**kwargs):
# 正常逻辑:取出手机号/用户名/邮箱+密码--》去数据校验--》校验通过-->签发token--》返回给前端
# 高级逻辑:使用序列化类做上述逻辑
serializer=self.get_serializer(data=request.data)
if serializer.is_valid(): # 执行 三层认证
# 校验通过:会把user,access和refresh都放到序列化类对象中--》返回给前端、
# 现在在视图类中----》有个序列化类--》把视图类中变量给序列化类---》序列化类的变量给视图类--》借助于context给[字典]
refresh = serializer.context.get('refresh')
access = serializer.context.get('access')
return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})
else:
return Response({'code': 101, 'msg': serializer.errors})
序列化类
from rest_framework import serializers
import re
from .models import UserInfo
from rest_framework.exceptions import ValidationError
class LoginJWTSerializer(serializers.Serializer):
username = serializers.CharField() # 可能是 用户名 手机号 邮箱
password=serializers.CharField()
def _get_user(self,attrs):
# 1 校验用户
username = attrs.get('username')
password = attrs.get('password')
# 2 去数据库 查询用户---》username可能是手机号,邮箱,用户名--》查的字段不一样
# 2.1 正则匹配,是不是手机号
if re.match(r'^1[3-9][0-9]{9}$', username):
user = UserInfo.objects.filter(mobile=username).first()
elif re.match('^.+@.+$', username):
user = UserInfo.objects.filter(email=username).first()
else:
user = UserInfo.objects.filter(username=username).first()
if user and user.check_password(password):
return user
else:
raise ValidationError('用户名或密码错误')
def validate(self, attrs):
# 取出 手机号/用户名/邮箱+密码--》数据库校验--》校验通过签发 access和refresh,放到context中
user=self._get_user(attrs)
# 签发token--》通过user对象,签发token
token = RefreshToken.for_user(user)
self.context['access'] = str(token.access_token)
self.context['refresh'] = str(token)
return attrs # 不返回不行:因为源码中校验了是否为空--》
总结
# 1 校验数据,放到序列化类的 validate中,而不放在视图类的方法中乐
# 2 视图类和序列化类直接交互变量
serializer.context
# 3 user.check_password 必须是auth的user表,校验密码使用它
# 4 attrs必须返回值,返回空报错
# 5 视图类的方法校验失败的else中:也要return Response
# 6 如何签发token
token = RefreshToken.for_user(user)
self.context['access'] = str(token.access_token)
self.context['refresh'] = str(token)
2自定义用户表
签发roken
不扩写auth
只要重写def _get_user的逻辑就可以了
2.1 新建用户表
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
user_type=models.IntegerField(choices=((1,'注册用户'),(2,'普通管理员'),(3,'超级管理员')),default=1)
@property
def is_authenticated(self):
return True
2.2 登陆签发
2.2.1 路由
# 127.0.0.1:8000/app01/api/v1/our_jwt/login/--->post请求
router.register('our_jwt', UserOurJWTView, 'our_jwt')
# 127.0.0.1:8000/app01/api/v1/publish/--->get
router.register('publish', PublishView, 'publish')
2.2.2 视图类
class UserOurJWTView(GenericViewSet):
serializer_class = LoginOurJWTSerializer
@action(methods=['POST'],detail=False)
def login(self,request,*args,**kwargs):
serializer=self.get_serializer(data=request.data)
if serializer.is_valid():
refresh = serializer.context.get('refresh')
access = serializer.context.get('access')
return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})
else:
return Response({'code': 101, 'msg': serializer.errors})
2.2.3 序列化类
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from .models import User
class LoginOurJWTSerializer(serializers.Serializer):
username = serializers.CharField() # 可能是 用户名 手机号 邮箱
password=serializers.CharField()
def _get_user(self,attrs):
# 1 校验用户
username = attrs.get('username')
password = attrs.get('password')
user=User.objects.filter(username=username,password=password).first()
if user:
return user
else:
raise ValidationError('用户名或密码错误')
def validate(self, attrs):
user=self._get_user(attrs)
token = RefreshToken.for_user(user)
self.context['access'] = str(token.access_token)
self.context['refresh'] = str(token)
return attrs
2.3 认证类
2.3.1 认证类
from rest_framework_simplejwt.authentication import JWTAuthentication
from .models import User
class JWTOurAuth(JWTAuthentication):
def authenticate(self, request):
# 取出用户携带的access---》放请求头中:Authorization
token = request.META.get('HTTP_AUTHORIZATION')
if token:
# 校验token--》validated_token 返回的就是可以信任的payload
validated_token = self.get_validated_token(token)
user_id = validated_token['user_id']
user = User.objects.filter(pk=user_id).first()
return user, token
else:
raise AuthenticationFailed('请携带登录信息')
2.3.2 使用
# 登陆后才能访问
from .authentication import JWTOurAuth
class PublishView(GenericViewSet):
authentication_classes = [JWTOurAuth]
def list(self,request):
return Response('get')
标签:username,登录,方式,get,self,access,token,user
From: https://www.cnblogs.com/dreammooncy/p/18145930