首页 > 解决方案 > 在 Django 中使用 Knox Token 从 DRF Token 中的令牌字符串获取用户对象

问题描述

我有与 Django 相关的问题。当每个用户登录页面时,我正在使用 Knox 令牌身份验证为每个用户生成令牌。

现在我想为每个将发送的请求使用该令牌,这样我就可以获得该令牌的相应用户。我def dashboard(request)还在 Django 中为每个 URL 路由使用自定义函数示例。

我在 youtube 上看到有从令牌获取用户的选项,但没有功能

    class UserAPI(generics.RetrieveAPIView):
        permission_classes = [
         permissions.IsAuthenticated,
        ]
        serializer_class = UserSerializer

        def get_object(self):
          return self.request.user

那么是否有一种乳清可以从自定义函数中的令牌中获取相应的用户

标签: pythondjangoauthenticationdjango-rest-knox

解决方案


太好了,我在几个小时内发现 knox 没有将完整的 token_key 存储在数据库中。

我们可以获得的真实令牌是这样的: a512529e7ffceaa8406ceb616d088b3422ad15811a5eb470e8f4c4896c9aa649

在数据库中 token_key 默认存储a512529e。8位数。

使用此过滤对象:

knox_object = AuthToken.objects.filter(token_key__startswith=token[:8]).first() 然后获取用户对象 knox_object.user.username

或者您可以更快地使用它

from knox.settings import CONSTANTS
knox_object = AuthToken.objects.filter(token_key=token[:CONSTANTS.TOKEN_KEY_LENGTH]).first()

来自 knox 源代码

class CONSTANTS:
    '''
    Constants cannot be changed at runtime
    '''
    TOKEN_KEY_LENGTH = 8
    DIGEST_LENGTH = 128
    SALT_LENGTH = 16

    def __setattr__(self, *args, **kwargs):
        raise Exception('''
            Constant values must NEVER be changed at runtime, as they are
            integral to the structure of database tables
            ''')


CONSTANTS = CONSTANTS()

可以看到TOKEN_KEY_LENGTH是 8 位数字。

我写了一个简单的函数来做到这一点

from knox.models import AuthToken
from knox.settings import CONSTANTS
def get_user_from_token(token):
    objs = AuthToken.objects.filter(token_key=token[:CONSTANTS.TOKEN_KEY_LENGTH])
    if len(objs) == 0:
        return None
    return objs.first().user

现在生活更轻松。:)

是的,我改进并发布了它。

你可以试试我的叉子。如果您只是想@smart_token_user在任何 GET/POST/PUT/... 方法之前添加。

https://github.com/xros/django-rest-knox

只需 git clone,然后pip install ./

我写了一个装饰器。

有了这个,在我们的应用程序views.py中我们可以很容易地通过这样做来获取用户对象,@smart_token_user将修改请求处理程序。request.user只有在令牌有效时,我们才能拥有一个attr。所有无效的尝试都将被 HTTP 401 Unauthorized 响应丢弃。有了这个装饰器,生活可以更轻松。

from knox.models import smart_token_user

class CheckUserEmail(generics.RetrieveAPIView):
    permission_classes = (IsAuthenticated,)

    @smart_token_user
    def get(self, request):
        return Response({
            "username": request.user.username,
            "email": request.user.email,
            "password": request.user.password,
        }, status=status.HTTP_200_OK)

或者,如果您愿意,也可以像原来一样使用:authentication_classes = (TokenAuthentication,)

class CheckUserEmail(generics.RetrieveAPIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    
    def get(self, request):
        return Response({
            "username": request.user.username,
            "email": request.user.email,
            "password": request.user.password,
        }, status=status.HTTP_200_OK)

推荐阅读