Angular 4 CLI中如何提取Django发送的CSRF Token以提交POST表单?
Hey there! Let's work through that CSRF token issue you're hitting when refactoring your app from Node.js to Django. This is a super common hiccup with front-end/back-end setups, so we'll get it sorted step by step.
First, Double-Check Django's CSRF Configuration
Before diving into Angular, make sure your Django backend is set up to send the CSRF cookie properly:
Verify CSRF Middleware is Enabled
In yoursettings.py, confirmdjango.middleware.csrf.CsrfViewMiddlewareis in theMIDDLEWARElist (it's included by default, but it never hurts to check):MIDDLEWARE = [ # ... other middleware ... 'django.middleware.csrf.CsrfViewMiddleware', # ... other middleware ... ]Ensure CSRF Cookie is Set for API Views
If you're using API-style views (not rendering Django templates), use theensure_csrf_cookiedecorator to force Django to send the CSRF cookie with the response. For example, create a dedicated endpoint to fetch the token:from django.http import HttpResponse from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def csrf_token_view(request): return HttpResponse(status=204) # No content needed, just set the cookieAdd this to your
urls.py:from django.urls import path from .views import csrf_token_view urlpatterns = [ path('api/csrf/', csrf_token_view, name='csrf-token'), # ... your other routes ... ]CORS Configuration (If Cross-Domain)
If Angular is running on a different port (likelocalhost:4200) than Django (e.g.,localhost:8000), you need to set up CORS to allow cookie sharing:- Install
django-cors-headers:pip install django-cors-headers - Update
settings.py:INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... rest of your middleware ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", # Your Angular dev server URL ] CORS_ALLOW_CREDENTIALS = True # Critical for sending cookies across domains
- Install
Angular Side: Auto-Fetch and Attach CSRF Token
Angular doesn't automatically pull the Django CSRF cookie by default, so we'll set up an HTTP interceptor to handle this for all requests.
Create a CSRF Interceptor
Make a new filecsrf.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>> { // Grab the CSRF cookie from the browser const csrfToken = this.getCookie('csrftoken'); if (csrfToken) { // Clone the request and add the CSRF header req = req.clone({ headers: req.headers.set('X-CSRFToken', csrfToken) }); } return next.handle(req); } // Helper function to extract cookies by name private getCookie(name: string): string | null { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift() || null; return null; } }Register the Interceptor in App Module
Updateapp.module.tsto include the interceptor so it applies to all HTTP requests:import { NgModule } from '@angular/core'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { CsrfInterceptor } from './csrf.interceptor'; @NgModule({ imports: [HttpClientModule], providers: [ { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true } ] }) export class AppModule { }Fetch CSRF Cookie Before POST Requests
To make sure the cookie is available before sending a POST request, call the Django CSRF endpoint first. Create a simple servicecsrf.service.ts:import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class CsrfService { constructor(private http: HttpClient) {} loadCsrfToken() { return this.http.get('/api/csrf/', { withCredentials: true }); } }Then use this in your component before submitting the form:
import { Component } from '@angular/core'; import { CsrfService } from './csrf.service'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-form', templateUrl: './form.component.html' }) export class FormComponent { formData = { /* Your form fields here */ }; constructor(private csrfService: CsrfService, private http: HttpClient) {} onSubmit() { // First load the CSRF cookie, then send the POST request this.csrfService.loadCsrfToken().subscribe(() => { this.http.post('/api/submit-form/', this.formData, { withCredentials: true }) .subscribe( response => console.log('Success!', response), error => console.error('Error:', error) ); }); } }
Key Notes to Remember
- Django names its CSRF cookie
csrftoken, so make sure your interceptor looks for that exact name. - The
withCredentials: trueoption in Angular's HTTP requests is essential for sending cookies cross-domain. - If you're using Django's class-based views, you can add the
@ensure_csrf_cookiedecorator to thegetmethod to set the cookie when the page loads.
Once you have all these pieces in place, your Angular app should automatically pick up and send the CSRF token with every POST request, and Django will validate it correctly.
内容的提问来源于stack exchange,提问作者Shiv Kumar

