Angular17对接Django时get_token()与CSRF_COOKIE不匹配求助
Angular 17 + Django CSRF令牌不匹配问题解决方案
核心问题分析
你的配置和实现存在几个关键冲突,导致令牌不匹配:
- Django CSRF存储方式错误:
CSRF_USE_SESSIONS = True将令牌存在Session中而非Cookie,Angular无法直接读取Session内容。 - Cookie权限限制:
CSRF_COOKIE_HTTPONLY = True禁止前端JS读取Cookie,Angular无法获取令牌;CSRF_COOKIE_SECURE = True在HTTP环境下(localhost开发)不会设置Cookie。 - 自定义令牌获取方式错误:通过接口返回令牌的方式,无法保证与Django当前会话绑定的Cookie令牌一致。
解决方案步骤
1. 修正Django配置(settings.py)
调整CSRF和CORS相关配置,让令牌能被Angular正确获取并传递:
CSRF_TRUSTED_ORIGINS = [ "http://localhost:4200", ] # 保持与Angular默认匹配的Cookie名称 CSRF_COOKIE_NAME = 'XSRF-TOKEN' # 关闭Session存储,改用Cookie存储CSRF令牌 CSRF_USE_SESSIONS = False # 开发环境禁用Secure Cookie(HTTPS环境再开启) CSRF_COOKIE_SECURE = False # 允许前端JS读取CSRF Cookie,供Angular HttpClient使用 CSRF_COOKIE_HTTPONLY = False CSRF_COOKIE_DOMAIN = 'localhost' CSRF_COOKIE_PATH = '/' # CORS配置保持现有正确项 CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", ] CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_METHODS = [ 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', ] CORS_ALLOW_HEADERS = [ 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'X-XSRF-TOKEN', 'x-requested-with', ]
2. 简化后端CSRF令牌接口
不需要自定义返回令牌的接口,改为触发Django自动设置CSRF Cookie:
from django.http import HttpResponse from django.middleware.csrf import get_token def obt_csrf_token(request): # 触发Django生成并设置CSRF Cookie get_token(request) return HttpResponse(status=204)
这个接口的作用是让Django在响应中写入XSRF-TOKEN Cookie,而非返回令牌内容。
3. 调整Angular端实现
删除自定义的CsrfService,利用Angular HttpClient的自动XSRF处理能力:
- 在
app.module.ts中配置HttpClientXsrfModule:
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'; @NgModule({ declarations: [/* 你的组件 */], imports: [ HttpClientModule, // 配置与Django匹配的Cookie和请求头名称 HttpClientXsrfModule.withOptions({ cookieName: 'XSRF-TOKEN', headerName: 'X-XSRF-TOKEN' }) ], providers: [], bootstrap: [/* 根组件 */] }) export class AppModule { }
- 发送登录请求时,只需启用
withCredentials以携带Cookie:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { constructor(private http: HttpClient) {} login(credentials: { username: string; password: string }) { return this.http.post( 'http://localhost:8000/procesar_iniciar_sesion/', credentials, { withCredentials: true } // 必须开启,携带Cookie到后端 ); } }
4. 验证流程
- 重启Django和Angular服务。
- 打开浏览器开发者工具,进入
Application > Cookies > localhost,确认存在XSRF-TOKEN。 - 点击登录按钮,查看
Network面板中POST请求的请求头,确认包含X-XSRF-TOKEN,且值与Cookie中的令牌一致。 - 后端Django会自动验证该请求头,无需额外处理(确保全局启用了
django.middleware.csrf.CsrfViewMiddleware中间件)。
关键注意事项
- 生产环境部署时,需将
CSRF_COOKIE_SECURE = True重新开启,确保仅在HTTPS环境下传输Cookie。 - 所有跨域请求必须携带
withCredentials: true,否则Cookie不会被传递到后端。 - 不要手动生成或返回CSRF令牌,依赖Django和Angular的自动机制即可保证令牌一致性。
内容的提问来源于stack exchange,提问作者Lázaro Bertín
相关产品推荐
相关产品推荐

