太好了,我在几个小时内发现 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)