DRF API在Angular应用中POST请求遇CSRF验证失败,Postman可正常调用
嘿,这个问题我之前在做DRF+Angular项目时也踩过坑!核心原因是Django的CSRF保护机制在拦截你的Angular请求——Postman能正常工作是因为它默认不会触发浏览器的Cookie/session流程,而Angular在浏览器环境下必须遵守Django的CSRF验证规则。下面分两步给你解决:
一、Django/DRF端配置
首先确保后端的CSRF和跨域配置正确:
检查DRF认证类
在项目的settings.py中,确保REST_FRAMEWORK的认证类包含SessionAuthentication(CSRF验证依赖session):REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', # 如果用了Token认证可以保留 ], }确认CSRF中间件启用
检查settings.py的MIDDLEWARE列表,确保有django.middleware.csrf.CsrfViewMiddleware(默认是启用的,但最好确认位置在SessionMiddleware之后):MIDDLEWARE = [ # ...其他中间件 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', # ...其他中间件 ]配置跨域支持(如果前后端跨域)
如果你的Angular项目(比如localhost:4200)和DRF后端(比如localhost:8000)不在同一域名,需要用django-cors-headers处理跨域:- 安装依赖:
pip install django-cors-headers - 在
settings.py中添加配置:INSTALLED_APPS = [ # ...其他APP 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 要放在CsrfViewMiddleware前面 # ...其他中间件 'django.middleware.csrf.CsrfViewMiddleware', # ...其他中间件 ] # 允许你的Angular域名 CORS_ALLOWED_ORIGINS = ['http://localhost:4200'] # 允许携带Cookie(关键!否则CSRF Cookie无法传递) CORS_ALLOW_CREDENTIALS = True
- 安装依赖:
二、Angular5端配置
Angular的HttpClient会自动处理CSRF,但需要和Django的规则匹配:
配置XSRF策略
在app.module.ts中,导入并配置HttpClientXsrfModule,让它使用Django的CSRF Cookie和头名称:import { NgModule } from '@angular/core'; import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'; @NgModule({ imports: [ HttpClientModule, HttpClientXsrfModule.withOptions({ cookieName: 'csrftoken', // Django默认的CSRF Cookie名 headerName: 'X-CSRFToken' // Django期望的CSRF请求头名 }) ], // ...其他配置 }) export class AppModule { }发送请求时携带Credentials
在你的Angular服务中,发送POST请求时要设置withCredentials: true,确保Cookie被携带:import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class EventService { constructor(private http: HttpClient) { } createEvent(eventData: any) { // 替换成你的API端点 return this.http.post('/api/events/', eventData, { withCredentials: true }); } }
额外小技巧
开发环境下,你可以先在浏览器访问一次Django的后台页面(比如http://localhost:8000/admin),登录后浏览器会自动获取CSRF Cookie,之后Angular的请求就能正常带上这个Cookie了。
内容的提问来源于stack exchange,提问作者dease

