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

本地向Django API发POST请求时出现CSRF令牌错误(Angular2)

解决Django API与Angular2 POST请求的CSRF错误

这个错误的核心原因是Django的CSRF保护机制在起作用:所有非GET的请求(比如POST)必须携带有效的CSRF token,你的Angular请求只设置了Content-Type,缺少这个关键的token,所以被拒绝了。

下面分两步来解决问题:

一、Django端配置检查与调整

首先确保你的Django项目已经正确启用了CSRF相关的组件,并且处理好跨域(如果Angular和Django运行在不同端口的话):

  1. 确认CSRF中间件和Session组件启用
    在settings.py里,确保INSTALLED_APPS包含django.contrib.sessions,MIDDLEWARE列表里有以下两个中间件(顺序不能错):

    MIDDLEWARE = [
        # ... 其他中间件
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        # ... 其他中间件
    ]
    
  2. 处理跨域请求(如果Angular和Django不在同一端口)
    如果你的Angular运行在localhost:4200,Django在127.0.0.1:8000,属于跨域场景,需要安装并配置django-cors-headers:

    • 安装:pip install django-cors-headers
    • 在INSTALLED_APPS里添加:'corsheaders'
    • 在MIDDLEWARE里把corsheaders.middleware.CorsMiddleware放在django.middleware.common.CommonMiddleware之前:
      MIDDLEWARE = [
          'corsheaders.middleware.CorsMiddleware',
          'django.middleware.common.CommonMiddleware',
          # ... 其他中间件
      ]
      
    • 添加跨域配置:
      CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie
      CORS_ORIGIN_WHITELIST = [
          'http://localhost:4200',  # Angular的地址
      ]
      

二、Angular2代码修改

Django默认会把CSRF token存在名为csrftoken的cookie里,Angular需要读取这个cookie并把它放到请求头的X-CSRFToken字段中。这里有两种推荐的实现方式:

方法一:使用Angular的HttpClientXsrfModule(推荐)

Angular提供了专门处理XSRF的模块,可以自动帮你读取cookie并添加请求头,配置起来很简单:

  1. 在AppModule中导入并配置HttpClientXsrfModule:

    import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';
    
    @NgModule({
      declarations: [/* 你的组件 */],
      imports: [
        HttpClientModule,
        HttpClientXsrfModule.withOptions({
          cookieName: 'csrftoken',  // Django的CSRF cookie名称
          headerName: 'X-CSRFToken', // Django要求的请求头名称
        }),
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
  2. 简化你的login服务代码(Angular会自动处理token和Content-Type):

    import { HttpClient } from '@angular/common/http';
    import { map } from 'rxjs/operators';
    
    // ...
    
    constructor(private http: HttpClient) { }
    
    public login(user: any) {
      return this.http.post("http://127.0.0.1:8000/auth_api/login/", user, { withCredentials: true })
        .pipe(map((data: any) => data));
    }
    

    注:withCredentials: true是跨域场景下必须的,确保cookie能被正常携带。

方法二:手动读取cookie并设置请求头

如果不想用Angular的XSRF模块,可以手动实现cookie读取和请求头设置:

  1. 添加一个读取cookie的工具函数:

    private getCookie(name: string): string {
      const ca = document.cookie.split(';');
      for (let cookie of ca) {
        const trimmedCookie = cookie.trim();
        if (trimmedCookie.startsWith(`${name}=`)) {
          return trimmedCookie.substring(name.length + 1);
        }
      }
      return '';
    }
    
  2. 修改login方法,添加CSRF token到请求头:

    public login(user: any){
      const body = JSON.stringify(user);
      const headers = new Headers();
      headers.append('Content-Type', 'application/json');
      headers.append('X-CSRFToken', this.getCookie('csrftoken')); // 添加CSRF token
      return this.http.post("http://127.0.0.1:8000/auth_api/login/", body, { 
        headers: headers,
        withCredentials: true  // 跨域时必须开启,携带cookie
      })
        .map((data: Response) => data.json())
    }
    

注意事项

  • 不要用@csrf_exempt装饰器绕过CSRF检查,这会带来严重的安全风险,只有在完全信任请求来源的情况下才考虑使用。
  • 确保你的Angular和Django的域名/端口配置正确,跨域时CORS_ORIGIN_WHITELIST要包含Angular的准确地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:46:19