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

   这个是序列化器的源码,在__init__方法中实现了字段:

class JSONWebTokenSerializer(Serializer): def __init__(self, *args, **kwargs): super(JSONWebTokenSerializer, self).__init__(*args, **kwargs) self.fields[self.username_field] = serializers.CharField() # username字段 self.fields['password'] = PasswordField(write_only=True) # password字段 @property def username_field(self): return get_username_field() def validate(self, attrs): credentials = { self.username_field: attrs.get(self.username_field), 'password': attrs.get('password') } if all(credentials.values()): user = authenticate(**credentials) # 这里是执行认证。 if user: if not user.is_active: msg = _('User account is disabled.') raise serializers.ValidationError(msg) payload = jwt_payload_handler(user) # 拿到荷载信息 return { 'token': jwt_encode_handler(payload), # 荷载信息放进去,来生成JWT的token字符串 'user': user } else: msg = _('Unable to log in with provided credentials.') raise serializers.ValidationError(msg) else: msg = _('Must include "{username_field}" and "password".') msg = msg.format(username_field=self.username_field) raise serializers.ValidationError(msg)

   也就是说,在执行JSONWebTOkenAPIView的post()方法时,会走一次数据库查询,根据提交的用户名和密码来拿到用户对象。并且在序列化器中,会生成token()信息。他们都是配置好的一些函数:

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER jwt_decode_handler = api_settings.JWT_DECODE_HANDLER jwt_get_username_from_payload = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER

   (我们可不可以自己写一个验证类来覆盖它,然后用于多端登录呢?手机号,邮箱等都可以登录)

   我们继续来看post()方法:

def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) # 可以发现它有一个自带的序列化器 if serializer.is_valid(): # 直接进行验证 user = serializer.object.get('user') or request.user # request.user等于已经登录的用户 token = serializer.object.get('token') # token等于生成的jwt随机字符串 response_data = jwt_response_payload_handler(token, user, request) # 设置返回信息 response = Response(response_data) if api_settings.JWT_AUTH_COOKIE: # 未设置,不走 expiration = (datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA) response.set_cookie(api_settings.JWT_AUTH_COOKIE, token, expires=expiration, httponly=True) return response # 直接返回 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # 没验证通过

   OK,自动签发的流程已经走完了。

   大概的缕一缕,它自己有序列化器,并且在序列化器中完成了JWT字符串的拼接,最后进行返回。

验证流程

   现在我们再来看一下,当用户登录后,再次访问的验证流程,最开始肯定走认证:

authentication_classes = [JSONWebTokenAuthentication]

   我们都知道,在APIView中的dispatch()方法中的initial()方法中,会有下面这三条代码:

self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request) # 详细的这三个代码的执行步骤,尤其是认证,可以查看之前的文章

   也就是先走认证,走认证时会统一执行一个叫做authenticators()的方法。我们直接找JSONWebTokenAuthentication中的authenticators()方法即可。

   这个类没有authenticators()这个方法,所以它继承类谁呢?

class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):

   所以我们要找的其实是BaseJSONWebTokenAuthentication中的authenticators()方法。

   终于,找到了:

def authenticate(self, request): jwt_value = self.get_jwt_value(request) # 获取jwt字符串,进行解析。也就是[ JWT 字符串 ],这个字符串的内容,排除前缀,感兴趣可以看看 if jwt_value is None: return None # 如果没有JWT验证字符串,则返回None try: # 一系列的异常捕获,均来自于内置的jwt模块 payload = jwt_decode_handler(jwt_value) # 解码荷载部分 except jwt.ExpiredSignature: msg = _('Signature has expired.') # 签证已过期 raise exceptions.AuthenticationFailed(msg) except jwt.DecodeError: msg = _('Error decoding signature.') # 解码签证时出错 raise exceptions.AuthenticationFailed(msg) except jwt.InvalidTokenError: raise exceptions.AuthenticationFailed() # 无效令牌 user = self.authenticate_credentials(payload) # 如果都没出错,则执行这里 return (user, jwt_value) # 返回user对象,这个会赋值给reque.user,这个会jwt字符串会赋值给request.auth =================Request.user中关于权限认证的地方 for authenticator in self.authenticators: try: user_auth_tuple = authenticator.authenticate(self) # 这里会返回一个user except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple # 进行赋值 self.user=user ,self.auth = jwt_value return

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

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