太好了,我在几个小时内发现 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
现在生活更轻松。 :)
是的,我改进并发布了。
你可以试试我的叉子。如果您只是想在任何 GET/POST/PUT/... 方法之前添加 @smart_token_user。
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)