You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Django中CSRF“Forbidden Cookie未设置”错误?

Your problem boils down to cross-origin cookie restrictions and missing configuration on both the Django backend and Angular frontend. When your apps are hosted on the same server, the same-origin policy doesn’t block cookies, but cross-domain setups require explicit, targeted setup. Let’s walk through the fixes step by step:

1. Correct Django CORS & CSRF Settings

First, update your settings.py to properly handle cross-origin requests and secure cookies:

Update CORS Configurations

Since you’re using django-cors-headers, these settings are critical to allow cookies (credentials) across domains:

# Enable cross-origin credentials (required for cookies to be sent/received)
CORS_ALLOW_CREDENTIALS = True

# Whitelist your exact frontend origin (include protocol, IP, and port)
CORS_ORIGIN_WHITELIST = [
    "https://127.0.0.1:4200",
    "https://192.xxx.x.xx:7002"  # Include backend's own origin for testing
]

# Trust the frontend origin for CSRF validation
CSRF_TRUSTED_ORIGINS = [
    "127.0.0.1:4200",
    "192.xxx.x.xx:7002"
]

# Ensure cookies are only sent over HTTPS (both apps use HTTPS, so this is safe)
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

# Remove any CSRF_COOKIE_DOMAIN setting if present (it blocks cross-domain cookies)
# CSRF_COOKIE_DOMAIN = "your-domain.com"  # Delete or comment this line

Django 1.11 doesn’t natively support the SameSite cookie attribute, which is required for cross-domain cookies in modern browsers. Create a middleware to add this attribute to your CSRF cookie:

# Common/customMiddleware.py
class ProcessCSRFCookie:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        # Modify the CSRF cookie to allow cross-domain access
        if 'csrftoken' in response.cookies:
            csrf_cookie = response.cookies['csrftoken']
            csrf_cookie['samesite'] = 'None'  # Required for cross-domain
            csrf_cookie['secure'] = True       # Must be paired with SameSite=None
        return response

Add this middleware to your MIDDLEWARE list after django.middleware.csrf.CsrfViewMiddleware:

MIDDLEWARE = [
    'Common.customMiddleware.ProcessRequest',
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'Common.customMiddleware.ProcessCSRFCookie',  # Add here
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Django’s CsrfViewMiddleware doesn’t automatically set the CSRF cookie for GET requests. In your login view, explicitly generate the CSRF token to trigger the cookie being sent:

from django.middleware.csrf import get_token

def login_view(request):
    # Generate CSRF token to set the cookie in the response
    get_token(request)
    # Your existing login logic here
    return JsonResponse({"status": "success"})

3. Configure Angular to Send Credentials

Your Angular app needs to explicitly tell the browser to send cookies with cross-domain requests. You can do this globally with an interceptor or per-request:

Create an interceptor to add withCredentials: true to all HTTP requests:

// src/app/credentials.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class CredentialsInterceptor implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Clone the request and enable credentials
    const modifiedRequest = request.clone({ withCredentials: true });
    return next.handle(modifiedRequest);
  }
}

Register the interceptor in your AppModule:

// src/app/app.module.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CredentialsInterceptor } from './credentials.interceptor';

@NgModule({
  // ... other imports and declarations
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: CredentialsInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }

Per-Request Alternative

If you prefer not to use an interceptor, add withCredentials: true to individual requests:

// Example login request
this.http.get('https://192.xxx.x.xx:7002/login', { withCredentials: true })
  .subscribe(response => {
    // Handle login success
  });

// Example POST request
this.http.post('https://192.xxx.x.xx:7002/api/your-endpoint', yourData, { withCredentials: true })
  .subscribe(response => {
    // Handle response
  });

Final Checks

  • Clear your browser’s cache and cookies to ensure old, misconfigured cookies aren’t interfering.
  • Verify in your browser’s dev tools (Application > Cookies) that the csrftoken cookie is being set for the backend domain.
  • Ensure both your Angular app (ng server --ssl true) and Django API are running over HTTPS (required for Secure cookies).

内容的提问来源于stack exchange,提问作者Haroon Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 20:17:45