即使在生成令牌后尝试访问 Django 中的 JWT 身份验证页面时也会出现未经授权的 401

问题描述 投票:0回答:1

我是一名学生,正在尝试自学 JWT 身份验证。我创建了一个基本的登录页面,登录后用户应该看到一个欢迎页面,上面写着“Welcome {username}”。 然而,即使登录后,欢迎页面仍显示

欢迎光临 获取/欢迎/ HTTP 401 未经授权 允许:获取、选项 内容类型:application/json 变化:接受 WWW-身份验证:承载领域=“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'),
]

我的登录.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>

我的设置.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分钟了,错误仍然存在。

django django-rest-framework jwt django-rest-framework-simplejwt
1个回答
0
投票

您返回了 JsonResponse,其中包含访问令牌,但之后您必须手动将令牌值添加到下一个请求标头中。

response = JsonResponse({'message': 'Login successful'})
response['Authorization'] = f'Bearer {token}'
return response

此代码将无法正常工作,因为每个请求和响应都被视为独立的。您的下一个请求将不包含授权令牌,这会导致

401 Unauthorized
错误。

我的建议是仅返回访问令牌,而不设置用于响应的

Authorization
键。

return JsonResponse({'message': 'Login successful', 'token': token})

您可以通过将其保存在前端的 cookie 或本地存储中来使用此令牌。

© www.soinside.com 2019 - 2024. All rights reserved.