React对接Django SessionAuthentication时CSRF Token缺失致请求被禁
Django + React SessionAuthentication 中CSRF Token无法读取的问题
更新说明:因内容过长,已简化表述
我正尝试在React(端口3000)与Django(端口8000)中实现SessionAuthentication,但遇到CSRF Token无法在React中设置的问题,导致/api/user请求返回FORBIDDEN。
复现步骤
注册、登录、刷新页面,运行以下命令:
Django(端口8000):
python3 -m venv backendvirtualenv && source backendvirtualenv/bin/activate pip install -r requirements.txt python manage.py makemigrations python manage.py migrate python manage.py runserver
React(端口3000):
npm install npm run build npm start
相关代码配置
Django配置(settings.py):
CORS_ALLOWED_ORIGINS = [ 'http://localhost', 'http://127.0.0.1', 'http://0.0.0.0', 'http://127.0.0.1:3000', ] CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True INSTALLED_APPS = [ ... 'corsheaders', MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', ), } SESSION_COOKIE_HTTPONLY = True # Default value is True, which is recommended SESSION_COOKIE_SAMESITE = 'Lax' # Consider 'None' if strictly necessary and secure is set SESSION_COOKIE_SECURE = False # Non-Production Port 80 CSRF_COOKIE_HTTPONLY = False # Should generally be False to allow JavaScript to read the value CSRF_COOKIE_SECURE = False # Non-Production Port 80
Django视图(views.py):
class UserLogin(APIView): permission_classes = (permissions.AllowAny,) authentication_classes = (SessionAuthentication,) ## def post(self, request): ... if serializer.is_valid(raise_exception=True): user = serializer.check_user(data) <-- authenticate is in here login(request, user) return Response(serializer.data, status=status.HTTP_200_OK) class UserView(APIView): permission_classes = (permissions.IsAuthenticated,) authentication_classes = (SessionAuthentication,) ## def get(self, request): .. serializer = UserSerializer(request.user) return Response({'user': serializer.data}, status=status.HTTP_200_OK)
React代码(App.js):
axios.defaults.xsrfCookieName = 'csrftoken'; axios.defaults.xsrfHeaderName = 'X-CSRFToken'; axios.defaults.withCredentials = true; const client = axios.create({ baseURL: "http://127.0.0.1:8000" }); .... function submitLogin(e) { e.preventDefault(); client.post( "/api/login", { email: email, password: password } ).then(function(res) { setTimeout(() => { const csrftoken = Cookies.get('csrftoken'); const sessionid = Cookies.get('sessionid'); console.log("XXX /api/login csrftoken:" + csrftoken); console.log("XXX /api/login sessionid:" + sessionid); console.log('cookies', document.cookie) }, 100); setCurrentUser(true); });
问题分析
从日志可见,CSRF Token无法被读取:
App.js:103 XXX /api/login csrftoken:undefined App.js:104 XXX /api/login sessionid:undefined App.js:106 cookies <--- 此处document.cookie为空
但/api/login的响应中确实存在CSRF Token:
Set-Cookie: csrftoken=yO8XukEnOSWYgwYxae4nd7c2OEHF2UQG; expires=Mon, 10 Mar 2025 22:26:02 GMT; Max-Age=31449600; Path=/; SameSite=Lax Set-Cookie: sessionid=rbj2ewpg11sx0t7q9j16ika01nk46074; expires=Mon, 25 Mar 2024 22:26:02 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax Vary:
已尝试的方案
- 将axios更新至最新版本1.6.7
- 测试过Chrome和Edge浏览器
- 代理配置方案无效
- 使用fetch()时CSRF Token可被浏览器Cookie保存,但Axios和superagent均无效,希望解决Axios的适配问题
内容的提问来源于stack exchange,提问作者Axil
相关产品推荐
相关产品推荐

