首页 文章

Django到Angular 6:CSRF令牌丢失或不正确,即使它已在 Headers 中设置

提问于
浏览
0

我正在尝试从Angular 6应用程序向Django后端发出POST请求 . 即使我在头文件中包含csrf令牌,Django也会将403 Forbidden错误记录为“CSRF令牌丢失或不正确” . 我的代码如下(在我尝试满足Django的过程中使用无关的 Headers ):

角度成分:

import { Injectable } from '@angular/core';
  import { HttpClient, HttpHeaders } from '@angular/common/http';
  import { SharedService } from '../../shared.service';
  import { CookieService } from 'ngx-cookie-service';

  @Injectable({
    providedIn: 'root'
  })
  export class EmailService {
// http options used for making any writing API calls with csrf token
private httpOptions: any;
csrfToken;

constructor(private http: HttpClient, private cookieService: CookieService) {
  // Set the csrf token
  this.http.get(SharedService.contactEmailUrl).subscribe((data) => (this.csrfToken = data['csrfToken']), (error1) => console.log(error1));
}

sendMailgunContactMessage(payload) {
  // Configure CSRF token header options
  this.httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/x-www-form-urlencoded',
      'X-CSRFToken': this.csrfToken,
      'x-csrftoken': this.csrfToken,
      'X-XSRF-TOKEN': this.csrfToken,
      'XSRF-TOKEN': this.csrfToken,
      'X-CSRF': this.csrfToken,
      csrfmiddlewaretoken: this.csrfToken,
      csrftoken: this.csrfToken
    }),
    withCredentials: true
  };

  let body = {
    csrfmiddlewaretoken: this.csrfToken,
    content: payload
  };

  return this.http.post(SharedService.contactEmailUrl, body, this.httpOptions);
}
}

Django设置:

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'XYZ'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

CSRF_COOKIE_SECURE = False
CSRF_USE_SESSIONS = False

CORS_ORIGIN_ALLOW_ALL = True

CORS_ORIGIN_WHITELIST = (
    'XYZ'
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'X-CSRFToken',
    'x-csrftoken',
    'X-XSRF-TOKEN',
    'XSRF-TOKEN',
    'csrfmiddlewaretoken',
    'csrftoken',
    'X-CSRF'
)

CORS_ALLOW_CREDENTIALS = True

# Application definition

INSTALLED_APPS = (
    'corsheaders',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

MIDDLEWARE_CLASSES = (
    'corsheaders.middleware.CorsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
   'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

MIDDLEWARE = (
    'django.middleware.csrf.CsrfViewMiddleware'
)

ROOT_URLCONF = 'django_project.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'django_project.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'debug.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
# Allow Django from all hosts. This snippet is installed from
# /var/lib/digitalocean/allow_hosts.py

import os
import netifaces

# Find out what the IP addresses are at run time
# This is necessary because otherwise Gunicorn will reject the connections
def ip_addresses():
    ip_list = []
    for interface in netifaces.interfaces():
        addrs = netifaces.ifaddresses(interface)
        for x in (netifaces.AF_INET, netifaces.AF_INET6):
            if x in addrs:
                ip_list.append(addrs[x][0]['addr'])
    return ip_list

# Discover our IP address
ALLOWED_HOSTS = ip_addresses()

Django查看:

from django.shortcuts import render
from django.http import HttpResponse
from .controllers import *
import json
from django.middleware.csrf import get_token
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.decorators.csrf import csrf_protect

# Create your views here.

@ensure_csrf_cookie
def email(request):
    if request.method == 'POST':
        json_body = json.loads(request.body)
        response = HttpResponse(send_contact_message(json_body))
        return response
    elif request.method == 'GET':
        csrf_token = get_token(request)
        response = HttpResponse('{ "csrfToken": "' + csrf_token + '" }')
        return response

注意:Django没有在cookie中设置csrftoken cookie,不确定这是否重要 .

为什么我在标头中发回的CSRF令牌没有被Django验证?

1 回答

  • 0

    在你的模块中尝试使用它而不是csrf头

    @NgModule({ 
        providers: [ HttpXsrfInterceptor,
        { provide: HTTP_INTERCEPTORS, useExisting: HttpXsrfInterceptor, multi: true },
        { provide: HttpXsrfTokenExtractor, useClass: HttpXsrfCookieExtractor }, 
        { provide: XSRF_COOKIE_NAME, useValue: 'XSRF-TOKEN' }, 
        { provide: XSRF_HEADER_NAME, useValue: 'X-XSRF-TOKEN' }, ] })
    

    用django发回的值替换'xsrf-token'和'x-xsrf-token' .

    来自:https://angular.io/api/common/http/HttpClientXsrfModule

相关问题