Angular5向Django提交JSON数据遇403 CSRF验证失败,如何实现CSRF_TOKEN?
Ah, I’ve dealt with this exact headache before when pairing Angular with Django! The {% csrf_token %} tag works seamlessly in Django templates, but since Angular is handling your frontend separately, we need to take a different approach to grab and send the CSRF token correctly. Here’s how to fix it:
Step 1: Understand Where Django Stores the CSRF Token
Django automatically sets a cookie named csrftoken for authenticated users (and even for anonymous users in most cases). Our goal is to pull this token from the cookie and include it in our Angular HTTP requests.
Step 2: Option 1 - Manually Add the Token to Individual Requests
If you only need to add the token to a few specific requests, you can write a helper function to extract the cookie and attach it to the request headers:
Helper Function to Get CSRF Token
Add this method to your component or service:
private getCsrfToken(): string | null { // Extract the csrftoken cookie from document.cookie const cookiePair = document.cookie.split('; ').find(row => row.startsWith('csrftoken=')); return cookiePair ? cookiePair.split('=')[1] : null; }
Use the Token in Your POST Request
When sending your JSON data, include the token in the X-CSRFToken header (Django looks for this header specifically):
import { HttpClient, HttpHeaders } from '@angular/common/http'; // In your component/service constructor constructor(private http: HttpClient) {} submitDatabaseTableData(data: any) { const csrfToken = this.getCsrfToken(); const requestHeaders = new HttpHeaders({ 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken || '' }); return this.http.post('/survey/creatDatabaseTable', data, { headers: requestHeaders }); }
Step 3: Option 2 - Use an Angular HTTP Interceptor (Recommended)
For a cleaner solution that automatically adds the CSRF token to every relevant request (POST, PUT, DELETE), create an HTTP interceptor. This way you don’t have to repeat the token logic for every request.
Create the CSRF Interceptor
Make a new file csrf.interceptor.ts:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class CsrfInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // Extract the CSRF token from cookies const csrfToken = document.cookie.split('; ') .find(row => row.startsWith('csrftoken=')) ?.split('=')[1]; // If we have a token, clone the request and add the header if (csrfToken) { const modifiedReq = req.clone({ headers: req.headers.set('X-CSRFToken', csrfToken) }); return next.handle(modifiedReq); } // No token found, proceed with original request return next.handle(req); } }
Register the Interceptor in Your App Module
Update app.module.ts to include the interceptor:
import { NgModule } from '@angular/core'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { CsrfInterceptor } from './csrf.interceptor'; @NgModule({ // ... existing declarations, imports, etc. providers: [ { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true // Allows multiple interceptors } ] }) export class AppModule { }
Important Notes to Avoid Pitfalls
- Cookie Name Check: Ensure Django’s
CSRF_COOKIE_NAMEsetting is set tocsrftoken(this is the default, but double-check if you’ve modified it). - Cross-Domain Requests: If your Angular app is hosted on a different domain than Django, you’ll need to add your Angular domain to Django’s
CSRF_TRUSTED_ORIGINSsetting insettings.py, and ensure cookies are marked asSameSite=None; Secureif using HTTPS. - Request Methods: Django only requires CSRF validation for unsafe methods (POST, PUT, PATCH, DELETE) — GET requests don’t need the token.
内容的提问来源于stack exchange,提问作者Khushal Goyal

