Angular 4 向 Django 提交POST表单的CSRF令牌问题(跟进提问)
Hey there! I noticed you’re using @csrf_exempt as a quick workaround for your Angular-Django POST issue—and while that gets things working temporarily, it’s not a secure long-term solution. Let’s fix this properly so you can keep CSRF protection enabled (critical for your app’s security) while getting your form submissions to work smoothly.
First: Clean Up the Django Side
Let’s ditch the @csrf_exempt decorator and set up proper CSRF handling:
Confirm CSRF Middleware is Enabled
Check yoursettings.pyto ensure'django.middleware.csrf.CsrfViewMiddleware'is in yourMIDDLEWARElist—it’s included by default in new Django projects, but double-checking never hurts.Update Your View
Remove the@csrf_exemptdecorator. Your view should look like this (we can add@csrf_protectexplicitly for clarity, though the middleware handles it automatically):from django.http import JsonResponse from django.views.decorators.csrf import csrf_protect @csrf_protect def empty_form(request): if request.method == "POST": message = "Post received successfully!" else: message = "Get request received" return JsonResponse({'message': message})Enable CORS (For Cross-Origin Requests)
Since Angular runs onlocalhost:4200by default and Django onlocalhost:8000, you need to allow cross-origin requests. Install thedjango-cors-headerspackage:pip install django-cors-headersThen add these settings to
settings.py:INSTALLED_APPS = [ # ... your existing apps 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # Add this at the TOP of MIDDLEWARE 'django.middleware.common.CommonMiddleware', # ... other middleware ] CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", ] CORS_ALLOW_CREDENTIALS = True # Lets cookies (including CSRF token) be sent cross-origin
Next: Configure Angular to Send the CSRF Token
Angular’s HttpClient can automatically grab the CSRF cookie from Django and include it in your POST requests. Here’s how to set it up:
Add a Cookie Helper Function
Create a helper to extract Django’scsrftokencookie (Django names it this by default):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; }Modify Your
send_sample_formMethod
Include theX-CSRFTokenheader in your POST request:import { HttpClient, HttpHeaders } from '@angular/common/http'; // Inside your component class constructor(private http: HttpClient) {} send_sample_form() { const csrfToken = this.getCookie('csrftoken'); const headers = new HttpHeaders({ 'X-CSRFToken': csrfToken || '', 'Content-Type': 'application/json' // Adjust if sending form data instead of JSON }); this.http.post('http://localhost:8000/your-endpoint/', {}, { headers: headers, withCredentials: true }).subscribe( response => console.log('Success:', response), error => console.error('Error:', error) ); }Optional: Use an Interceptor for All Requests
If you don’t want to add the header manually to every request, create an HTTP interceptor that automatically includes the CSRF token: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>> { const csrfToken = this.getCookie('csrftoken'); if (csrfToken) { req = req.clone({ setHeaders: { 'X-CSRFToken': csrfToken } }); } return next.handle(req); } 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.ts:import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { CsrfInterceptor } from './csrf.interceptor'; @NgModule({ // ... imports and declarations providers: [ { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true } ] }) export class AppModule {}
How It All Works
- Django sets the
csrftokencookie when you first access any endpoint (trigger a GET request if needed to initialize it). - Angular grabs that cookie and sends it in the
X-CSRFTokenheader with every POST request. - Django’s CSRF middleware verifies the header matches the cookie value, allowing the request to proceed.
Test this out: start both your Django server and Angular app, submit the form, and you should get a successful response without any CSRF errors!
内容的提问来源于stack exchange,提问作者Shiv Kumar

