Django+Angular登录用户POST请求返回403 Forbidden问题排查
Hey there, let's troubleshoot this 403 Forbidden issue together—this is a super common pain point when pairing DRF with Angular, so I’ve got some solid leads to check.
First, let’s break down what we know:
- Unauthenticated POSTs (login/register) work fine, so those views are likely exempt from CSRF checks.
- DRF’s browsable API works because it automatically handles the CSRF token in forms.
- Your authenticated POSTs fail with 403, which points to Angular not sending the correct CSRF token header.
Let’s start with fixing your Angular XSRF configuration
You’re mixing Angular’s old HttpModule and new HttpClientModule, which is probably causing your CSRF setup to not work as expected. The CookieXSRFStrategy is part of the deprecated HttpModule, but you’re using HttpClient (the modern version), so we need to switch to the correct configuration:
- Update your AppModule:
- Remove the
HttpModuleimport entirely—you don’t need it alongsideHttpClientModule. - Replace your old XSRF provider with
HttpClientXsrfModuleconfigured to match Django’s CSRF cookie and header names.
- Remove the
Here’s the adjusted code:
import { BrowserModule } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { NgModule } from '@angular/core'; import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { RegisterComponent } from './register/register.component'; import { LoginComponent } from './login/login.component'; import { AlertComponent } from './_directives/alert.component'; import { ProfileComponent } from './profile/profile.component'; import { AuthGuardService } from './_guards/auth-guard.service'; import { AlertService } from './_services/alert.service'; import { AuthService } from './_services/auth.service'; import { UserService } from './_services/User.service'; @NgModule({ declarations: [ AppComponent, RegisterComponent, LoginComponent, AlertComponent, ProfileComponent, ], imports: [ BrowserModule, FormsModule, ReactiveFormsModule, AppRoutingModule, HttpClientModule, // Configure XSRF for Django's cookie/header names HttpClientXsrfModule.withOptions({ cookieName: 'csrftoken', headerName: 'X-CSRFToken', }) ], providers: [ // Remove the old XSRFStrategy provider here ], bootstrap: [AppComponent] }) export class AppModule { }
- Ensure your HTTP requests let Angular auto-inject the CSRF header:
YourHttpOptionssets theContent-Type(which you need forapplication/json), but make sure you’re not overriding or blocking Angular from adding theX-CSRFTokenheader automatically. TheHttpClientwill handle this as long as theHttpClientXsrfModuleis configured correctly—you don’t need to manually add the header to yourHttpOptions.
Next, check your Django configuration (especially if you’re using separate front/back-end ports)
If your Angular app runs on localhost:4200 and DRF on localhost:8000 (cross-origin), you need to update two settings in settings.py:
Install and configure django-cors-headers:
This lets your backend accept requests from your Angular origin.- Install it:
pip install django-cors-headers - Add to
INSTALLED_APPSandMIDDLEWARE:INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # Place this early in the list 'django.middleware.common.CommonMiddleware', # ... rest of your middleware ] - Allow your Angular origin:
CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", ]
- Install it:
Trust your Angular origin for CSRF:
Add your front-end URL toCSRF_TRUSTED_ORIGINS:CSRF_TRUSTED_ORIGINS = [ "http://localhost:4200", ]
Verify the token is being sent (using browser dev tools)
Open your browser’s DevTools > Network tab, then send the failing POST request. Check:
- Cookies: Under the Application tab, confirm there’s a
csrftokencookie present. - Request Headers: Look for
X-CSRFTokenin the request headers—its value should match thecsrftokencookie.
If the cookie exists but the header isn’t sent, double-check your Angular HttpClientXsrfModule configuration. If the cookie doesn’t exist, ensure your Django template includes {% csrf_token %} (you have this in your code, which is good) or that you’re hitting a DRF endpoint that sets the CSRF cookie (like a simple GET endpoint) before sending authenticated POSTs.
One last check: DRF view CSRF exemptions
Make sure your authenticated views don’t have @csrf_exempt (they shouldn’t, since you want CSRF protection), and that your unauthenticated views (login/register) do have @csrf_exempt or use DRF’s AllowAny permission with CSRF exemption if needed.
内容的提问来源于stack exchange,提问作者Marcus Grass

