You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF中djangorestframework-simplejwt认证前端无法正常工作求助

Django SimpleJWT 浏览器认证失败问题解决

我开发了一个包含注册、登录、用户信息接口的应用,Postman测试所有接口都正常返回结果,但使用djangorestframework-simplejwt做认证时,浏览器访问需要认证的接口返回401未授权错误,求解决。


相关配置与代码

settings.py 配置

from datetime import timedelta

# JWT Configuration
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

# JWT Settings
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=20),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),

    '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',
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

    'JTI_CLAIM': 'jti',

}

INSTALLED_APPS = [
    # ... 其他应用
    'rest_framework',
    'rest_framework_simplejwt',
    # ... 其他应用
]

登录视图(Views.py)

class UserLoginView(APIView):
    def post(self, request, format=None):
        q = QueryDict(request.body)
        query_dict = q.dict()
        json_object = json.dumps(query_dict, indent=4)
        reqBody = json.loads(json_object)
        email = reqBody['email']
        password = reqBody['password']
        user = authenticate(email=email, password=password)
        print('user')
        print(user)
        if user is not None:
            token = get_tokens_for_user(user)
            Account = customer.objects.get(email=email)
            request.session['email'] = Account.email
            request.session['id'] = Account.id
            request.session['name'] = Account.firstname
            request.session['cust_status'] = Account.cust_status
            request.session['os_name'] = Account.os_name
            request.session['user_type'] = Account.flag
            request.session['username'] = str(Account.firstname) + str(Account.lastname)

            return Response({'token': token, 'msg': 'Login Success'}, status=status.HTTP_200_OK)
        else:
            return Response({'errors': {'non_field_errors': ['Email or Password is not Valid']}},
                            status=status.HTTP_404_NOT_FOUND)

需要认证的测试API视图

@api_view(['GET'])
@authentication_classes((TokenAuthentication,))
@permission_classes((IsAuthenticated,))
def test_view(request):
    return HttpResponse("Allowed")

错误信息

Test View
GET /example_view
HTTP 401 Unauthorized
Allow: OPTIONS, GET
Content-Type: application/json
Vary: Accept
WWW-Authenticate: Token

{
    "detail": "Authentication credentials were not provided."
}

问题原因及解决步骤

1. 认证类不匹配(核心问题)

全局配置使用的是JWTAuthentication,但测试视图硬编码了TokenAuthentication(这是DRF自带的Token认证,并非SimpleJWT的JWT认证逻辑),导致认证规则不兼容。

解决方法:

  • 移除测试视图的@authentication_classes((TokenAuthentication,))装饰器,直接使用全局配置的JWT认证:
@api_view(['GET'])
@permission_classes((IsAuthenticated,))
def test_view(request):
    return HttpResponse("Allowed")
  • 或者显式指定JWT认证类:
from rest_framework_simplejwt.authentication import JWTAuthentication

@api_view(['GET'])
@authentication_classes((JWTAuthentication,))
@permission_classes((IsAuthenticated,))
def test_view(request):
    return HttpResponse("Allowed")

2. 浏览器请求需正确携带Authorization头

浏览器请求时,必须在请求头中添加格式正确的认证信息:

Authorization: Bearer <你的access_token>

注意:Bearer与token之间有一个空格,access_token是登录接口返回的token.access字段值(登录接口返回的token是包含access和refresh的字典)。

3. 优化登录视图代码(可选)

登录视图中QueryDict转JSON的操作完全冗余,可直接用request.data获取参数;同时如果是纯API服务,无需操作session(JWT本身是无状态认证):

class UserLoginView(APIView):
    def post(self, request, format=None):
        email = request.data.get('email')
        password = request.data.get('password')
        user = authenticate(email=email, password=password)
        
        if user is not None:
            token = get_tokens_for_user(user)
            return Response({'token': token, 'msg': 'Login Success'}, status=status.HTTP_200_OK)
        else:
            return Response({'errors': {'non_field_errors': ['Email or Password is not Valid']}},
                            status=status.HTTP_401_UNAUTHORIZED)

内容的提问来源于stack exchange,提问作者Alam kazi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 03:24:26