Получение 401 unauthorized при попытке доступа к странице с JWT-аутентификацией в Django даже после генерации токена
Я студент, пытающийся обучить себя JWT-аутентификации. Я создал базовую страницу входа в систему, и после входа в систему пользователь должен увидеть страницу приветствия, на которой написано Welcome {username}. Однако даже после входа в систему на странице приветствия написано
Приветствие GET /welcome/ HTTP 401 Неавторизованный Разрешить: GET, OPTIONS Content-Type: application/json Vary: Accept WWW-Authenticate: Bearer realm="api"
{ "detail": "Учетные данные для аутентификации не были предоставлены". }
Мой код выглядит следующим образом:
views.py
from django.http import JsonResponse
from django.shortcuts import render, redirect
from loginapp.models import User
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.urls import reverse
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
print("Username:", username)
print("Password:", password)
user = User.objects.filter(username=username).first()
#user = authenticate(username=username, password=password)
if user is not None and user.password == password:
refresh = RefreshToken.for_user(user)
token = str(refresh.access_token)
response = JsonResponse({'message': 'Login successful'})
response['Authorization'] = f'Bearer {token}'
return response
else:
return JsonResponse({'error_message': 'Invalid username or password.'}, status=400)
else:
return render(request, 'login.html')
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def welcome(request):
username = request.user.username
return Response({'message': f'Welcome, {username}!'})
мой urls.py выглядит следующим образом:
from django.urls import path
from loginapp import views
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.views import TokenRefreshView
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.login, name='login'),
path('welcome/',views.welcome, name='welcome'),
#path('welcome/<str:username>/', views.welcome, name='welcome'),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
my login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<div id="error-message"></div>
<form id="loginForm">
{% csrf_token %}
<label for="username">Username:</label>
<input type="text" id="username" name="username"><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password"><br>
<button type="submit">Login</button>
</form>
<script>
document.getElementById("loginForm").addEventListener("submit", function(event) {
event.preventDefault();
fetch("/", {
method: "POST",
body: new FormData(document.getElementById("loginForm"))
})
.then(response => {
if (response.ok) {
const token = response.headers.get('Authorization').split(' ')[1];
localStorage.setItem("jwtToken", token);
window.location.href = "/welcome";
} else {
return response.json();
}
})
.then(data => {
if (data.error_message) {
document.getElementById("error-message").innerText = data.error_message;
}
})
.catch(error => {
console.error("Error:", error);
});
});
</script>
</body>
</html>
my settings.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': True,
}
Может ли кто-нибудь точно определить, где может возникнуть проблема? Я использую базу данных MySQL, из которой я запрашиваю имя пользователя.
Я попробовал изменить в settings.py ACCESS_TOKEN_LIFETIME, но даже это уже 60 минут, а ошибка все еще сохраняется.
Вы вернули JsonResponse
с токеном доступа внутри него, но после этого вам придется вручную добавить значение токена в заголовок следующего запроса.
response = JsonResponse({'message': 'Login successful'})
response['Authorization'] = f'Bearer {token}'
return response
Этот код не будет работать должным образом, поскольку каждый запрос и ответ рассматриваются как независимые. Ваш следующий запрос не будет содержать токен авторизации, что приведет к ошибке 401 Unauthorized
.
Я рекомендую возвращать только токен доступа, не задавая Authorization
ключ для ответа.
return JsonResponse({'message': 'Login successful', 'token': token})
И вы можете использовать этот токен, сохранив его в cookie или локальном хранилище во фронтенде.