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

Angular 15与Flask API的CSRF保护配置故障排查求助

问题排查与解决方案

一、浏览器未设置XSRF-TOKEN Cookie的核心原因

1. 跨域(CORS)配置缺失

如果前后端运行在不同域名/端口下,浏览器同源策略会阻止Cookie写入,需在Flask端正确配置CORS:

from flask_cors import CORS

# 配置CORS,允许指定前端Origin,同时开启凭据支持
CORS(app, supports_credentials=True, origins=["http://你的Angular域名:端口"])

2. Cookie属性不符合浏览器要求

默认Set-Cookie属性可能不满足跨域或HTTPS场景要求,需补充关键属性:
修改inject_csrf_token函数,为XSRF-TOKEN Cookie添加必要配置:

@app.after_request
def inject_csrf_token(response):
    xsrf_token = generate_csrf()
    response.headers.set('X-XSRF-TOKEN', xsrf_token)
    # 配置Cookie属性,适配跨域/HTTPS场景
    response.set_cookie(
        'XSRF-TOKEN',
        xsrf_token,
        path='/',
        samesite='None',  # 跨域场景必须设为None
        secure=True,       # HTTPS环境必填,本地HTTP开发可移除
        httponly=False     # 必须设为False,Angular需要读取该Cookie
    )
    return response

二、Flask后端CSRF验证配置错误

flask-wtf默认监听的CSRF请求头是X-CSRFToken,但Angular默认发送X-XSRF-TOKEN,需修改Flask配置让它识别这个头:

app.config['CSRF_HEADER_NAME'] = 'X-XSRF-TOKEN'

这一步是核心,否则Flask会因找不到对应Token持续报错。

三、Angular前端配置优化

1. 简化HttpClientXsrfModule配置

已导入HttpClientXsrfModule的情况下,它会自动读取XSRF-TOKEN Cookie并在请求中携带X-XSRF-TOKEN头,无需手动构建headers:

import { HttpClientXsrfModule } from '@angular/common/http';

@NgModule({
  imports: [
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',  // 对应Flask设置的Cookie名
      headerName: 'X-XSRF-TOKEN' // 对应Flask配置的CSRF_HEADER_NAME
    })
  ]
})

2. 修正请求代码错误

你的代码存在变量名错误(this.token应为this.xsrfToken),且手动设置headers可能干扰Angular自动处理,建议简化请求:

constructor(private _http: HttpClient) {}

postData<T>(url: string, data: any): Observable<T> {
  return this._http.post<T>(url, data, { withCredentials: true });
}

只要开启withCredentials: true,Angular会自动完成CSRF Token的读取和携带。

3. 自定义拦截器方案(可选)

若需手动从响应头提取Token,确保存储格式符合Flask要求:

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class CsrfInterceptor implements HttpInterceptor {
  private xsrfToken: string | null = null;

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 为修改类请求添加CSRF头
    if (this.xsrfToken && ['POST', 'PUT', 'DELETE'].includes(req.method)) {
      req = req.clone({
        setHeaders: { 'X-XSRF-TOKEN': this.xsrfToken }
      });
    }

    return next.handle(req).pipe(
      tap(event => {
        // 从响应头提取并存储Token
        if (event.type === 4) { // 匹配HttpResponse类型
          const token = event.headers.get('X-XSRF-TOKEN');
          if (token) this.xsrfToken = token;
        }
      })
    );
  }
}

在app.module.ts注册拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true }
  ]
})

四、测试验证步骤

  1. 打开浏览器开发者工具→应用→Cookie,确认XSRF-TOKEN已写入。
  2. 发送POST请求时,查看请求头是否包含X-XSRF-TOKEN,值与Cookie一致。
  3. 检查Flask控制台,确认无CSRFError输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:15:31