问题描述
关于Django身份验证中间件,我有以下问题:
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self,request):
assert hasattr(request,'session'),(
"The Django authentication middleware requires session middleware "
"to be installed. Edit your MIDDLEWARE setting to insert "
"'django.contrib.sessions.middleware.SessionMiddleware' before "
"'django.contrib.auth.middleware.AuthenticationMiddleware'."
)
request.user = SimpleLazyObject(lambda: get_user(request))
正如您在此处看到的那样,中间件从后端调用方法get_user(在我的情况下为simple_jwt),并将此方法放入SimpleLazyObject
中,以便稍后进行评估。
def get_user(self,validated_token):
"""
Attempts to find and return a user using the given validated token.
"""
try:
user_id = validated_token[api_settings.USER_ID_CLaim]
except KeyError:
raise InvalidToken(_('Token contained no recognizable user identification'))
try:
user = User.objects.get(**{api_settings.USER_ID_FIELD: user_id})
except User.DoesNotExist:
raise AuthenticationFailed(_('User not found'),code='user_not_found')
if not user.is_active:
raise AuthenticationFailed(_('User is inactive'),code='user_inactive')
return user
我要做的是保留request.user = SimpleLazyObject(lambda: get_user(request))
,以便为使用它的应用程序提供用户实例,但对于我的自定义应用程序,我想添加类似的内容
伪代码
request.user_id = user_id from user (user_id = validated_token[api_settings.USER_ID_CLaim])
为了不查询数据库中对用户对象的每一个请求,以防万一我只需要user_id
,它已经直接在后端的get_user
方法中提供了。
问题–如何将user_id
从get_user()
传递到AuthenticationMiddleware.process_request()
并设置request.user_id
属性以请求而不评估SimpleLazyObject
?
奇怪的是,我无法在class JWTAuthentication(authentication.BaseAuthentication):
所属的get_user()
中分配要请求的属性
谢谢。
Internal Server Error: /auth/users/me/
Traceback (most recent call last):
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\asgiref\sync.py",line 330,in thread_handler
raise exc_info[1]
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\django\core\handlers\exception.py",line 38,in inner
response = await get_response(request)
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\django\utils\deprecation.py",line 126,in __acall__
response = await sync_to_async(
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\asgiref\sync.py",line 296,in __call__
ret = await asyncio.wait_for(future,timeout=None)
File "C:\ProgramData\Miniconda3\envs\entropy\lib\asyncio\tasks.py",line 440,in wait_for
return await fut
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\asgiref\current_thread_executor.py",line 23,in run
result = self.fn(*self.args,**self.kwargs)
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\asgiref\sync.py",line 334,in thread_handler
return func(*args,**kwargs)
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\django\contrib\auth\middleware.py",line 26,in process_request
request.user_id = _get_user_session_key(request)
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\django\contrib\auth\__init__.py",line 58,in _get_user_session_key
return get_user_model()._Meta.pk.to_python(request.session[SESSION_KEY])
File "C:\ProgramData\Miniconda3\envs\entropy\lib\site-packages\django\contrib\sessions\backends\base.py",line 65,in __getitem__
return self._session[key]
KeyError: '_auth_user_id'
解决方法
您已经具有可用的用户ID。它是从auth.get_user()中的会话中解码的,您可以将其复制到自己的MiddleWare中:
from django.contrib.auth import _get_user_session_key
request.user_id = _get_user_session_key(request)
这是Django私有API,不确定为什么将其保持私有。但是您也可以复制它实现的一种衬纸:
request.user_id = get_user_model()._meta.pk.to_python(
request.session[SESSION_KEY]
)