视图代码
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()