美文网首页
drf的token登录和原理

drf的token登录和原理

作者: kevin_lln | 来源:发表于2022-11-13 20:51 被阅读0次

    1.token登录实现

    参考django restframework文档关于TokenAuthentication

    1.1 在setting.py中加入authtoken

    INSTALLED_APPS = [
        ...
        'rest_framework.authtoken'
    ]
    REST_FRAMEWORK = {
        # 用于验证用户登录信息
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'rest_framework.authentication.BasicAuthentication',
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.TokenAuthentication',
        ]
    }
    

    1.2 迁移关于token相关数据表

    • python manage.py makemigrations
    • python manage.py migrate


      截屏2022-11-13 20.05.39.png

    1.3 url.py中配置路由

    from rest_framework.authtoken import views
    urlpatterns += [
        path('api-token-auth/', views.obtain_auth_token)
    ]
    

    1.4 postman测试接口

    截屏2022-11-13 20.08.57.png
    截屏2022-11-13 20.24.00.png

    2.登录原理

    通过接口获取token实现

    class ObtainAuthToken(APIView):
        ....
        def post(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            user = serializer.validated_data['user']
            # 查询authtoken_token表中的token.key
            # 如果没有则插入数据
            token, created = Token.objects.get_or_create(user=user)
            return Response({'token': token.key})
    obtain_auth_token = ObtainAuthToken.as_view()
    

    通过token进行接口验证

    # rest_framework/authentication.py
    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):
            # 获取token(Token ff000224e411d7676cc1e0da2d0a1ace6c372df1)并分割
            auth = get_authorization_header(request).split()
    
            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为ff000224e411d7676cc1e0da2d0a1ace6c372df1
                token = auth[1].decode()
            except UnicodeError:
                msg = _('Invalid token header. Token string should not contain invalid characters.')
                raise exceptions.AuthenticationFailed(msg)
    
            return self.authenticate_credentials(token)
    
        def authenticate_credentials(self, key):
            # 获取表authtoken_token的模型
            model = self.get_model()
            try:
                # 校验用户的token是否存在或有效
                token = model.objects.select_related('user').get(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)
    

    3.缺点

    • token是永久的,没有过期时间,泄漏会有问题
    • 分布式的应用,需要同步用户信息到每个服务器

    相关文章

      网友评论

          本文标题:drf的token登录和原理

          本文链接:https://www.haomeiwen.com/subject/vslkxdtx.html