drf JWT认证模块与自定制 (4)

   我们来看看user是怎么弄出来的。它是在BaseJSONWebTokenAuthentication类中定义的:

def authenticate_credentials(self, payload): User = get_user_model() # 返回模型!!不是记录对象 ,通过settings.py中的AUTH_USER_MODEL进行获取 username = jwt_get_username_from_payload(payload) # 获取payload中的用户名 if not username: # 如果没有用户名就抛出异常 msg = _('Invalid payload.') raise exceptions.AuthenticationFailed(msg) try: # 根据荷载中的用户名,在模型User中试图获取出用户的记录对象,也就是说这里会走数据库查询。 user = User.objects.get_by_natural_key(username) except User.DoesNotExist: # 如果User这个模型不存在则抛出异常,说明 msg = _('Invalid signature.') raise exceptions.AuthenticationFailed(msg) if not user.is_active: # 判断账户是否被禁用 msg = _('User account is disabled.') raise exceptions.AuthenticationFailed(msg) return user # 返回user 不用auth组件

   看完了上面的源码分析后,我们再来想一想,如果不用auth模块该怎么办?

   其实也很简单,我们自己造一个jwt然后将token这个随机字符串返回就好了。

   认证的时候我们重写一下认证类就好了,反正都是那一套逻辑。

  

手动签发

   我们的表中要有username以及password字段,使用JWT模块中生成token的几个函数,自己造就一个token。

# views.py from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER from users.models import User class LoginView(APIView): # 登录的时候签发token authentication_classes = [] def post(self,request): username=request.data.get('username') password=request.data.get('password') user=User.objects.filter(username=username,password=password).first() if user: # 能查到,登陆成功,手动签发 payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return CommonResponse('100','登陆成功',data={'token':token}) else: return CommonResponse('101', '登陆失败')

   如果你想实现多端登录,手机、用户名、邮箱等都能登录,这里也有一份代码,只不过配合了序列化器使用,比较复杂:

# 使用用户名,手机号,邮箱,都可以登录# # 前端需要传的数据格式 { "username":"lqz/1332323223/33@qq.com", # 用户名、或者手机号、或者邮箱 "password":"lqz12345" } # 视图 from rest_framework.views import APIView from rest_framework.viewsets import ViewSetMixin, ViewSet from app02 import ser class Login2View(ViewSet): # 跟上面完全一样 def login(self, request, *args, **kwargs): # 1 需要 有个序列化的类 login_ser = ser.LoginModelSerializer(data=request.data,context={'request':request}) # context参数类似与管道,与序列化器进行连接 # 2 生成序列化类对象 # 3 调用序列号对象的is_validad login_ser.is_valid(raise_exception=True) token=login_ser.context.get('token') # 从管道中取出token并返回 # 4 return return Response({'status':100,'msg':'登录成功','token':token,'username':login_ser.context.get('username')}) # 序列化类 from rest_framework import serializers from api import models import re from rest_framework.exceptions import ValidationError from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler class LoginModelSerializer(serializers.ModelSerializer): username=serializers.CharField() # 重新覆盖username字段,数据中它是unique,post,认为你保存数据,自己有校验没过 class Meta: model=models.User fields=['username','password'] def validate(self, attrs): print(self.context) # 在这写逻辑 username=attrs.get('username') # 用户名有三种方式 password=attrs.get('password') # 通过判断,username数据不同,查询字段不一样 # 正则匹配,如果是手机号 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: # 存在用户 # 校验密码,因为是密文,要用check_password if user.check_password(password): # 签发token payload = jwt_payload_handler(user) # 把user传入,得到payload token = jwt_encode_handler(payload) # 把payload传入,得到token self.context['token']=token self.context['username']=user.username return attrs else: raise ValidationError('密码错误') else: raise ValidationError('用户不存在') JWT验证

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxyyp.html