使用 djangorestframework-simplejwt 的 Django 会导致 POST 错误 403: Forbidden (CSRF cookie not set.): on /api/token/

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

我想设置一个带有 REST API 的简单 Django 后端。如果我尝试使用提供的 url 登录,但每次尝试登录时都会收到 403 错误:CSRF Verficatoin 失败。 CSRF cookie 未设置。

这是我用过的应用程序:

Django==4.1.10
# Rest Framework
djangorestframework==3.14.0
djangorestframework-api-key==2.3.0 
djangorestframework-simplejwt==5.2.2
markdown==3.4.4 
# CORS for rest api
django-cors-headers==4.2.0

和我的设置:

ALLOWED_HOSTS='*, localhost'
ALLOWED_ORIGINS='http://*, https://*'
CSRF_COOKIE_AGE=31449600
CSRF_COOKIE_NAME='csrftoken'
CSRF_USE_SESSIONS=False
CSRF_TRUSTED_ORIGINS='http://*, https://*'
CSRF_COOKIE_HTTPONLY=False
CSRF_COOKIE_SECURE=False
CSRF_COOKIE_DOMAIN = None
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CORS_ALLOW_ALL_ORIGINS=False
CORS_ALLOWED_ORIGIN_REGEXES=''
CORS_ALLOWED_ORIGINS='http://localhost:8888, http://127.0.0.1:8888'

服务器在端口 8888 上运行,命令为:python3 manage.py runserver 0.0.0.0:8888

中间件:

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

以及 Rest Framework 的设置:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework_api_key.permissions.HasAPIKey',
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        # 'rest_framework.authentication.TokenAuthentication',
        # 'rest_framework.authentication.SessionAuthentication',
        # 'rest_framework.authentication.BasicAuthentication', # only for testing      
    ],
    "DEFAULT_PARSER_CLASSES": [
        "rest_framework.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        "rest_framework.parsers.MultiPartParser",
    ],
}

这些网址在应用程序的介绍中:

    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),

现在,如果我尝试以下请求:

curl \                                                                                                                                                                                                                      
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"username": "my_username", "password": "my_password"}' \
  http://localhost:8888/api/token/

我收到错误代码 403,如上所述。

你有什么想法吗?我该如何解决这个问题?

致以诚挚的问候!

python django rest http-status-code-403 django-rest-framework-simplejwt
1个回答
0
投票

经过几个小时的测试,我找到了解决方案。 url 模式的顺序错误。我将其更改为:

urlpatterns = [
path('', admin.site.urls),
path('api/token/', csrf_exempt(TokenObtainPairView.as_view()), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),    

]

至:

urlpatterns = [
path('api/token/', csrf_exempt(TokenObtainPairView.as_view()), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),   
path('', admin.site.urls),

]

管理站点必须是最后一个条目,我删除了登录网址的 csrf 豁免。

谢谢阿蒂沙姆的回复。

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