在 django 中第一个访问令牌过期后用户注销
User logout after the first access token expires in django
用户在第一个访问令牌过期后注销。
如何在过期后自动创建和设置新的访问令牌?
自定义TokenRefreshView方法即可
观看次数
在您正在构建的程序中,转到视图部分并添加以下内容 class。
class CustomTokenRefreshView(TokenRefreshView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
# set Refresh and Access token in browser with Httponly cookie.
response = Response(serializer.validated_data, status=status.HTTP_200_OK)
response.set_cookie(
key=settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH'],
value=serializer.validated_data["refresh"],
domain=settings.SIMPLE_JWT['AUTH_COOKIE_DOMAIN'],
path=settings.SIMPLE_JWT['AUTH_COOKIE_PATH'],
expires=settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME'],
secure=settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
httponly=settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
samesite=settings.SIMPLE_JWT['AUTH_COOKIE_SAME_SITE']
)
response.set_cookie(
key=settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS'],
value=serializer.validated_data["access"],
domain=settings.SIMPLE_JWT['AUTH_COOKIE_DOMAIN'],
path=settings.SIMPLE_JWT['AUTH_COOKIE_PATH'],
expires=settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
secure=settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
httponly=settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
samesite=settings.SIMPLE_JWT['AUTH_COOKIE_SAME_SITE']
)
return response
网址
基于 class 的观看次数
views.CustomTokenRefreshView.as_view()
path('token/refresh/', views.CustomTokenRefreshView.as_view(), name='token_refresh'),
path('token/verify/', TokenVerifyView.as_view(), name='token_refresh'),
中间件
当然还要加上下面的内容
在您正在构建的程序中创建一个名为 middleware.py 的文件,然后添加这两个自定义 classes。
class MoveJWTCookieIntoTheBody(MiddlewareMixin):
"""
for Django Rest Framework JWT's POST "/token-refresh" endpoint --- check for a 'token' in the request.COOKIES
and if, add it to the body payload.
"""
def __init__(self, get_response):
super().__init__(get_response)
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/auth/token/verify/' and settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS'] in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['token'] = request.COOKIES[settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS']]
request._body = json.dumps(data).encode('utf-8')
class MoveJWTRefreshCookieIntoTheBody(MiddlewareMixin):
"""
for Django Rest Framework JWT's POST "/token-refresh" endpoint --- check for a 'token' in the request.COOKIES
and if, add it to the body payload.
"""
def __init__(self, get_response):
super().__init__(get_response)
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/auth/token/refresh/' and settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH'] in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['refresh'] = request.COOKIES[settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH']]
request._body = json.dumps(data).encode('utf-8')
设置
然后你必须在设置中添加这些。
import datetime
...
MIDDLEWARE = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'accounts.middleware.MoveJWTCookieIntoTheBody',
'accounts.middleware.MoveJWTRefreshCookieIntoTheBody'
]
...
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
# Custom_SIMPLE_JWT
'AUTH_COOKIE': 'token', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_ACCESS': 'access', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_REFRESH': 'refresh', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_DOMAIN': None, # A string like "example.com", or None for standard domain cookie.
'AUTH_COOKIE_SECURE': False, # Whether the auth cookies should be secure (https:// only).
'AUTH_COOKIE_HTTP_ONLY': True, # Http only cookie flag.It's not fetch by javascript.
'AUTH_COOKIE_PATH': '/', # The path of the auth cookie.
'AUTH_COOKIE_SAME_SITE': 'Lax', # Whether to set the flag restricting cookie leaks on cross-site requests.
# This can be 'Lax', 'Strict', or None to disable the flag.
}
The only problem is that it gives a new access_token whenever it is reloaded.
What do you think should be done?
用户在第一个访问令牌过期后注销。
如何在过期后自动创建和设置新的访问令牌?
自定义TokenRefreshView方法即可
观看次数
在您正在构建的程序中,转到视图部分并添加以下内容 class。
class CustomTokenRefreshView(TokenRefreshView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
# set Refresh and Access token in browser with Httponly cookie.
response = Response(serializer.validated_data, status=status.HTTP_200_OK)
response.set_cookie(
key=settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH'],
value=serializer.validated_data["refresh"],
domain=settings.SIMPLE_JWT['AUTH_COOKIE_DOMAIN'],
path=settings.SIMPLE_JWT['AUTH_COOKIE_PATH'],
expires=settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME'],
secure=settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
httponly=settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
samesite=settings.SIMPLE_JWT['AUTH_COOKIE_SAME_SITE']
)
response.set_cookie(
key=settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS'],
value=serializer.validated_data["access"],
domain=settings.SIMPLE_JWT['AUTH_COOKIE_DOMAIN'],
path=settings.SIMPLE_JWT['AUTH_COOKIE_PATH'],
expires=settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
secure=settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
httponly=settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
samesite=settings.SIMPLE_JWT['AUTH_COOKIE_SAME_SITE']
)
return response
网址
基于 class 的观看次数
views.CustomTokenRefreshView.as_view()
path('token/refresh/', views.CustomTokenRefreshView.as_view(), name='token_refresh'),
path('token/verify/', TokenVerifyView.as_view(), name='token_refresh'),
中间件
当然还要加上下面的内容
在您正在构建的程序中创建一个名为 middleware.py 的文件,然后添加这两个自定义 classes。
class MoveJWTCookieIntoTheBody(MiddlewareMixin):
"""
for Django Rest Framework JWT's POST "/token-refresh" endpoint --- check for a 'token' in the request.COOKIES
and if, add it to the body payload.
"""
def __init__(self, get_response):
super().__init__(get_response)
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/auth/token/verify/' and settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS'] in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['token'] = request.COOKIES[settings.SIMPLE_JWT['AUTH_COOKIE_ACCESS']]
request._body = json.dumps(data).encode('utf-8')
class MoveJWTRefreshCookieIntoTheBody(MiddlewareMixin):
"""
for Django Rest Framework JWT's POST "/token-refresh" endpoint --- check for a 'token' in the request.COOKIES
and if, add it to the body payload.
"""
def __init__(self, get_response):
super().__init__(get_response)
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/auth/token/refresh/' and settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH'] in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['refresh'] = request.COOKIES[settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH']]
request._body = json.dumps(data).encode('utf-8')
设置
然后你必须在设置中添加这些。
import datetime
...
MIDDLEWARE = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'accounts.middleware.MoveJWTCookieIntoTheBody',
'accounts.middleware.MoveJWTRefreshCookieIntoTheBody'
]
...
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
# Custom_SIMPLE_JWT
'AUTH_COOKIE': 'token', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_ACCESS': 'access', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_REFRESH': 'refresh', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_DOMAIN': None, # A string like "example.com", or None for standard domain cookie.
'AUTH_COOKIE_SECURE': False, # Whether the auth cookies should be secure (https:// only).
'AUTH_COOKIE_HTTP_ONLY': True, # Http only cookie flag.It's not fetch by javascript.
'AUTH_COOKIE_PATH': '/', # The path of the auth cookie.
'AUTH_COOKIE_SAME_SITE': 'Lax', # Whether to set the flag restricting cookie leaks on cross-site requests.
# This can be 'Lax', 'Strict', or None to disable the flag.
}
The only problem is that it gives a new access_token whenever it is reloaded.
What do you think should be done?