#python #django #django-rest-framework #django-rest-framework-simplejwt #cookie-httponly
Вопрос:
Пользователь выходит из системы после истечения срока действия первого токена доступа.
Как автоматически создать и установить новый токен доступа после истечения его срока действия?
Комментарии:
1. Вам просто нужно снова получить новый токен доступа …
2. Это прекрасно работает для почтальона, но я не знаю, как это реализовать в коде.
3. Пожалуйста, отредактируйте вопрос, чтобы ограничить его конкретной проблемой с достаточной детализацией для определения адекватного ответа.
Ответ №1:
Просто настройте метод TokenRefreshView
число просмотров
В создаваемой вами программе перейдите в раздел представления и добавьте следующий класс.
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
URL-адреса
для представлений на основе классов
число просмотров.CustomTokenRefreshView.as_view()
path('token/refresh/', views.CustomTokenRefreshView.as_view(), name='token_refresh'),
path('token/verify/', TokenVerifyView.as_view(), name='token_refresh'),
Промежуточный слой
Конечно, вы также должны добавить следующее.
Создайте файл под названием промежуточное программное обеспечение.py в создаваемой программе, затем добавьте эти два пользовательских класса.
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.
}
Единственная проблема заключается в том, что он выдает новый access_token всякий раз, когда он перезагружается.
Как вы думаете, что нужно сделать?