问题
I am using Django JWT to power up authentication system in my project.
Also, I have a middleware, and the problem is that inside it, the user is anonymous for some reason, while in the view I am able to access the correct user by request.user
. This issue is driving me crazy because some time ago this code worked perfectly ! Is this JWT's bug or I am doing something wrong ?
class TimezoneMiddleware(MiddlewareMixin):
def process_request(self, request):
# request.user is ANONYMOUS HERE !!!!
if not request.user.is_anonymous:
tzname = UserProfile.objects.get(user = request.user).tz_name
if tzname:
timezone.activate(pytz.timezone(tzname))
Relevant settings.py module:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_RENDERER_CLASSES': (
'djangorestframework_camel_case.render.CamelCaseJSONRenderer',
# Any other renders
),
'DEFAULT_PARSER_CLASSES': (
'djangorestframework_camel_case.parser.CamelCaseJSONParser',
# Any other parsers
),
}
JWT_AUTH = {
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_response_payload_handler',
# 'rest_authentication.views.jwt_response_payload_handler',
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_PUBLIC_KEY': None,
'JWT_PRIVATE_KEY': None,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': False,
'JWT_LEEWAY': 0,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_ALLOW_REFRESH': False,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': 'JWT',
}
I have also come across resources which helped me to retrieve the actual user, BUT ! I am still unable to set the timezone (timezone.activate(pytz.timezone(tzname))
seems to be ignored.
回答1:
Yes, this issue is due to the JWT. You can checkout the discussion for it https://github.com/GetBlimp/django-rest-framework-jwt/issues/45 To fix this you will have to create a custom middleware which will set the request.user
. Here is one I am using in my code:
from django.contrib.auth.middleware import get_user
from django.utils.functional import SimpleLazyObject
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class JWTAuthenticationMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.user = SimpleLazyObject(lambda:self.__class__.get_jwt_user(request))
return self.get_response(request)
@staticmethod
def get_jwt_user(request):
user = get_user(request)
if user.is_authenticated:
return user
jwt_authentication = JSONWebTokenAuthentication()
if jwt_authentication.get_jwt_value(request):
user, jwt = jwt_authentication.authenticate(request)
return user
Include this in the middlewares. It should come above all the middlewares which are using request.user
.
回答2:
@Atul Mishra: Thank you! Changed your version to the newest drf-jwt package (1.17.2). Seems like the the current github repository moved from this to here
from django.contrib.auth.middleware import get_user
from django.utils.functional import SimpleLazyObject
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class JWTAuthenticationInMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.user = SimpleLazyObject(lambda:self.__class__.get_jwt_user(request))
return self.get_response(request)
@staticmethod
def get_jwt_user(request):
# Already authenticated
user = get_user(request)
if user.is_authenticated:
return user
# Do JTW authentication
jwt_authentication = JSONWebTokenAuthentication()
authenticated = jwt_authentication.authenticate(request)
if authenticated:
user, jwt = authenticated
return user
来源:https://stackoverflow.com/questions/50793212/django-jwt-authentication-user-is-anonymous-in-middleware