TokenAutication源码分析

创建的token如何交给前端进行使用呢?   

  在官方文档说明中,将产生的這个token放在header中

TokenAutication认证原理   

  用户认证成功以后,会在服务端产生一个Token。并且服务端会将這个Token设置在header里面返回给用户。下次用户在进行登陆相关操作,就根据這个Token去Token表查找相应的用户,并把用户名根据Token提取出来。

  我们可以在后端通过request.auth获取用户传递过来的token

  那么如何通过Token取出用户的呢?先来看看源码:

class TokenAuthentication(BaseAuthentication):
      keyword = 'Token'
      model = None

      def get_model(self):
          if self.model is not None:
             return self.model
          from rest_framework.authtoken.models import Token
          return Token

      def authenticate(self, request):
          auth = get_authorization_header(request).split() # 调用get_authorization_header
          # auth = ["Token" ,"c4840b5226a65806c586c239345fce66caf12409"]
          if not auth or auth[0].lower() != self.keyword.lower().encode():
             return None

          if len(auth) == 1:
             msg = _('Invalid token header. No credentials provided.')
             raise exceptions.AuthenticationFailed(msg)
          elif len(auth) > 2:
             msg = _('Invalid token header. Token string should not contain spaces.')
             raise exceptions.AuthenticationFailed(msg)

          try:
             token = auth[1].decode() # 取出c4840b5226a65806c586c239345fce66caf12409
          except UnicodeError:
             msg = _('Invalid token header. Token string should not contain invalid characters.')
             raise exceptions.AuthenticationFailed(msg)

          return self.authenticate_credentials(token) # 然后调用authenticate_credentials

      def authenticate_credentials(self, key):
          model = self.get_model() # 返回Token model
          try:
              token = model.objects.select_related('user').get(key=key) # 然后通过key获取用户
          except model.DoesNotExist:
              raise exceptions.AuthenticationFailed(_('Invalid token.'))

          if not token.user.is_active:
              raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

          return (token.user, token) # 返回用户与token

  然后,我们到get_authorization_header()方法里面去看看:

def get_authorization_header(request):
    auth = request.META.get('HTTP_AUTHORIZATION', b'') # AUTHORIZATION這个就是之前服务端返回的,只不过Django会默认加上HTTP
    if isinstance(auth, text_type):
       # Work around django test client oddness
       auth = auth.encode(HTTP_HEADER_ENCODING)
    return auth # 返回"Token  c4840b5226a65806c586c239345fce66caf12409"

  经过上述过程,就完成了Token的获取操作。下面,我们来看看,這个Token是如何创建的:

  当用户进行登陆以后:

url(r'^api-token-auth/', views.obtain_auth_token)

  通过上述接口,进入到试图函数:

class ObtainAuthToken(APIView):
      throttle_classes = ()
      permission_classes = ()
      parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
      renderer_classes = (renderers.JSONRenderer,)
      serializer_class = AuthTokenSerializer

      def post(self, request, *args, **kwargs): # 调用這个方法
          serializer = self.serializer_class(data=request.data,context={'request': request})
          serializer.is_valid(raise_exception=True)
          user = serializer.validated_data['user']
          token, created = Token.objects.get_or_create(user=user) # 没有就创建
          return Response({'token': token.key}) # 将token返回
obtain_auth_token = ObtainAuthToken.as_view()

  从上面的分析来看,当用户没有产生Token,DRF则会给该用户生成一个Token。然后将這个Token返回给前端页面进行保存。

原文地址:https://www.cnblogs.com/vipchenwei/p/8043445.html