使用Django+djangorestframework-simplejwt请求/api/token/时出现403(CSRF cookie未设置)错误的解决咨询
Hey there, let's break down why you're hitting this 403 CSRF error when trying to get a JWT token, and fix it step by step:
1. 修正配置项的格式错误(最可能的原因)
Looking at your settings, several key configs are using string values instead of lists, which Django won't parse correctly:
ALLOWED_HOSTSshould be a list, not a string:ALLOWED_HOSTS = ['*', 'localhost']CSRF_TRUSTED_ORIGINSneeds to be a list too (note that wildcards likehttp://*might not work as expected in newer Django versions—if you're testing locally, specify exact origins instead):CSRF_TRUSTED_ORIGINS = ['http://localhost:8888', 'http://127.0.0.1:8888']CORS_ALLOWED_ORIGINSalso needs to be a list:CORS_ALLOWED_ORIGINS = ['http://localhost:8888', 'http://127.0.0.1:8888']
Django ignores string-formatted lists for these settings, which could be preventing it from recognizing your local server as a trusted origin, hence failing to set the CSRF cookie.
2. 调整Token接口的权限设置
Your global DEFAULT_PERMISSION_CLASSES includes IsAuthenticated and HasAPIKey, but the /api/token/ endpoint is meant for unauthenticated users to get their first token. You have two options here:
Option A: Override permissions for the Token views
Update your urls.py to add custom permission classes for the TokenObtainPairView:
from rest_framework.permissions import AllowAny from rest_framework_simplejwt.views import ( TokenObtainPairView, TokenRefreshView, TokenVerifyView, ) urlpatterns = [ path('api/token/', TokenObtainPairView.as_view(permission_classes=[AllowAny]), name='token_obtain_pair'), path('api/token/refresh/', TokenRefreshView.as_view(permission_classes=[AllowAny]), name='token_refresh'), path('api/token/verify/', TokenVerifyView.as_view(permission_classes=[AllowAny]), name='token_verify'), # ... other urls ]
Option B: Adjust global permissions and use permission classes per-view
If you want most of your API to require authentication, keep the global permissions but exclude public endpoints like the token views by setting their permissions explicitly (like the above example).
3. Verify CSRF middleware behavior for JWT
Since you're using JWT authentication (not session auth), the CSRF middleware shouldn't block your /api/token/ request—but if the above fixes don't work, you can explicitly disable CSRF for the token views by adding csrf_exempt:
from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name='dispatch') class CustomTokenObtainPairView(TokenObtainPairView): permission_classes = [AllowAny] # Then use this custom view in your urls: path('api/token/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
This is a last-resort fix though—usually the first two steps should resolve the issue.
4. Test with corrected curl command
After fixing the settings, try your curl request again. If you still run into issues, you can explicitly include the CSRF cookie in the request (though with the above fixes, this shouldn't be necessary):
# First get the CSRF cookie curl -c cookies.txt http://localhost:8888/api/token/ # Then send the login request with the cookie curl -X POST -b cookies.txt \ -H "Content-Type: application/json" \ -H "X-CSRFToken: $(grep csrftoken cookies.txt | awk '{print $7}')" \ -d '{"username": "my_username", "password": "my_password"}' \ http://localhost:8888/api/token/
Give these steps a try—most likely the format errors in your settings are the root cause. Let me know if you still run into issues!
备注:内容来源于stack exchange,提问作者Bandit

