django rest framework_jwt之认证的源码流程剖析

视图代码

 1 class UserViewset(BaseView):
 2     '''
 3         create:
 4         创建用户
 5         retrieve:
 6 
 7     '''
 8     queryset = User.objects.all()
 9     authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication) #认证类
10     def get_serializer_class(self):
11         if self.action == "retrieve":
12             return UserDetailSerializer
13         elif self.action == "create":
14             return UserRegSerializer
15 
16         return UserDetailSerializer
17 
18     def get_permissions(self):
19         if self.action == "retrieve":
20             return [permissions.IsAuthenticated()]
21         elif self.action == "create":
22             return []
23 
24         return []
25 
26     def create(self, request, *args, **kwargs):
27         serializer = self.get_serializer(data=request.data)
28         serializer.is_valid(raise_exception=True)
29         user = self.perform_create(serializer)
30         re_dict = serializer.data
31         payload = jwt_payload_handler(user)
32         re_dict["token"] = jwt_encode_handler(payload)
33         re_dict["name"] = user.name if user.name else user.username
34 
35         headers = self.get_success_headers(serializer.data)
36         return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
37 
38     def get_object(self):
39         return self.request.user
40 
41     def perform_create(self, serializer):
42         return serializer.save()

认证类JSONWebTokenAuthentication代码:

 1 class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
 2     """
 3     Clients should authenticate by passing the token key in the "Authorization"
 4     HTTP header, prepended with the string specified in the setting
 5     `JWT_AUTH_HEADER_PREFIX`. For example:
 6 
 7         Authorization: JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIj
 8     """
 9     www_authenticate_realm = 'api'
10 
11     def get_jwt_value(self, request):
12         auth = get_authorization_header(request).split() #获取请求里面的token
13         auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower() #获取认证方式
14 
15         if not auth:  #如果没有token就获取其cookie
16             if api_settings.JWT_AUTH_COOKIE:
17                 return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
18             return None
19 
20         if smart_text(auth[0].lower()) != auth_header_prefix: #看看是不是jwt认证
21             return None
22 
23         if len(auth) == 1: #认证的字符必须是由空格隔开的字符
24             msg = _('Invalid Authorization header. No credentials provided.')
25             raise exceptions.AuthenticationFailed(msg)
26         elif len(auth) > 2:
27             msg = _('Invalid Authorization header. Credentials string '
28                     'should not contain spaces.')
29             raise exceptions.AuthenticationFailed(msg)
30 
31         return auth[1]
32 
33     def authenticate_header(self, request):
34         """
35         Return a string to be used as the value of the `WWW-Authenticate`
36         header in a `401 Unauthenticated` response, or `None` if the
37         authentication scheme should return `403 Permission Denied` responses.
38         """
39         return '{0} realm="{1}"'.format(api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm) #返回响应

在父类BaseJSONWebTokenAuthentication中做认证判断:

 1 class BaseJSONWebTokenAuthentication(BaseAuthentication):
 2     """
 3     Token based authentication using the JSON Web Token standard.
 4     """
 5 
 6     def authenticate(self, request):  #开始认证
 7         """
 8         Returns a two-tuple of `User` and token if a valid signature has been
 9         supplied using JWT-based authentication.  Otherwise returns `None`.
10         """
11         jwt_value = self.get_jwt_value(request) #获取token
12         if jwt_value is None:
13             return None
14 
15         try:
16             payload = jwt_decode_handler(jwt_value) #获取用户的token的实体
17         except jwt.ExpiredSignature:
18             msg = _('Signature has expired.')
19             raise exceptions.AuthenticationFailed(msg)
20         except jwt.DecodeError:
21             msg = _('Error decoding signature.')
22             raise exceptions.AuthenticationFailed(msg)
23         except jwt.InvalidTokenError:
24             raise exceptions.AuthenticationFailed()
25 
26         user = self.authenticate_credentials(payload) #获取用户
27 
28         return (user, jwt_value)
29 
30     def authenticate_credentials(self, payload):
31         """
32         Returns an active user that matches the payload's user id and email.
33         """
34         User = get_user_model()
35         username = jwt_get_username_from_payload(payload) #获取用户名
36 
37         if not username:
38             msg = _('Invalid payload.')
39             raise exceptions.AuthenticationFailed(msg)
40 
41         try:
42             user = User.objects.get_by_natural_key(username) #获取用户
43         except User.DoesNotExist:
44             msg = _('Invalid signature.')
45             raise exceptions.AuthenticationFailed(msg)
46 
47         if not user.is_active:
48             msg = _('User account is disabled.')
49             raise exceptions.AuthenticationFailed(msg)
50 
51         return user

用户请求进来以后,首先进入dispatch函数:

 1     def dispatch(self, request, *args, **kwargs):
 2         """
 3         `.dispatch()` is pretty much the same as Django's regular dispatch,
 4         but with extra hooks for startup, finalize, and exception handling.
 5         """
 6         self.args = args
 7         self.kwargs = kwargs
 8         request = self.initialize_request(request, *args, **kwargs) #加载添加的认证类
 9         self.request = request
10         self.headers = self.default_response_headers  # deprecate?
11 
12         try:
13             self.initial(request, *args, **kwargs)  #初始化request
14 
15             # Get the appropriate handler method
16             if request.method.lower() in self.http_method_names:
17                 handler = getattr(self, request.method.lower(),
18                                   self.http_method_not_allowed)
19             else:
20                 handler = self.http_method_not_allowed
21 
22             response = handler(request, *args, **kwargs)
23 
24         except Exception as exc:
25             response = self.handle_exception(exc)
26 
27         self.response = self.finalize_response(request, response, *args, **kwargs)
28         return self.response

加载initialize_request:

 1     def initialize_request(self, request, *args, **kwargs):
 2         """
 3         Returns the initial request object.
 4         """
 5         parser_context = self.get_parser_context(request)
 6 
 7         return Request(
 8             request,
 9             parsers=self.get_parsers(),
10             authenticators=self.get_authenticators(),加载添加的认证类
11             negotiator=self.get_content_negotiator(),
12             parser_context=parser_context
13         )

初始化initial:

 1     def initial(self, request, *args, **kwargs):
 2         """
 3         Runs anything that needs to occur prior to calling the method handler.
 4         """
 5         self.format_kwarg = self.get_format_suffix(**kwargs)
 6 
 7         # Perform content negotiation and store the accepted info on the request
 8         neg = self.perform_content_negotiation(request)
 9         request.accepted_renderer, request.accepted_media_type = neg
10 
11         # Determine the API version, if versioning is in use.
12         version, scheme = self.determine_version(request, *args, **kwargs)
13         request.version, request.versioning_scheme = version, scheme
14 
15         # Ensure that the incoming request is permitted
16         self.perform_authentication(request) 开始认证
17         self.check_permissions(request)
18         self.check_throttles(request)

在request中做认证:

 1     def _authenticate(self):
 2         """
 3         Attempt to authenticate the request using each authentication instance
 4         in turn.
 5         """
 6         for authenticator in self.authenticators:
 7             try:
 8                 user_auth_tuple = authenticator.authenticate(self)
 9             except exceptions.APIException:
10                 self._not_authenticated()
11                 raise
12 
13             if user_auth_tuple is not None:
14                 self._authenticator = authenticator
15                 self.user, self.auth = user_auth_tuple
16                 return
17 
18         self._not_authenticated()

猜你喜欢

转载自www.cnblogs.com/arrow-kejin/p/9986713.html