碰到的一个跨域问题:自定义header,接口请求不通

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了碰到的一个跨域问题:自定义header,接口请求不通相关的知识,希望对你有一定的参考价值。

参考技术A 在和后台人员关于接口token的设置,我放在请求header中

结果,放到线上,请求报错:
Access to XMLHttpRequest at 'https://*******/Login/login' from origin '********' has been blocked by CORS policy: Request header field x-token is not allowed by Access-Control-Allow-Headers in preflight response.

一直以为是跨域的,后台能改的都改了。结果查资料才知道,是请求header中设置的x-token,在返回header中没有,将response的header里加上x-token就可以了。
浪费了好长时间,心好累

Django前后端分离跨域请求问题

一、问题背景

  之前使用django+vue进行前后端分离碰到跨域请求问题,跨域(域名或者端口不同)请求问题的本质是由于浏览器的同源策略导致的,当请求的响应不是处于同一个域名和端口下,浏览器不会接受响应,同源策略也是浏览器针对请求的安全问题所作出的一种保护行为。针对跨域问题,可以有下面的解决方式:

  • JSONP方式
  • 自定义中间件,设置响应头
  • 使用django-cors-headers包

二、解决方式

(一)自定义中间件

  JSONP本质上是利用html的一些不受同源策略影响的标签属性src,例如:<a>、<img>、<script>等标签的src属性,从而实现跨域请求,但是这种方法只支持GET的请求方式,这里暂不做过多讨论,主要说自定义中间件以及利用django-cors-headers包来实现跨域。

1、自定义中间件

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, process_request):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, process_response):
            response = self.process_response(request, response)
        return response

class CORSMiddleware(MiddlewareMixin):

    def process_response(self,request,response):
        # 添加响应头
        # 允许相应的域名来访问,多个域名中间以逗号隔开,如果全部可使用‘*‘
        response[Access-Control-Allow-Origin] = "*"
        # 允许携带的请求头,多个中间以逗号隔开
        response[Access-Control-Allow-Headers] = "Content-Type"
        # 允许发送的请求方式
        response[Access-Control-Allow-Methods] = "DELETE,PUT"
        return response

2、注册中间件(在settings文件中注册)

MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
     ...
     ...
    crm.utils.cors.CORSMiddleware #跨域中间件
]

(二)CORS(Cross-Origin Resource Sharing)

1、安装django-cors-headers包

pip install django-cors-headers #在对应的开发环境中安装

2、修改settings文件

  • 注册应用
# Application definition

INSTALLED_APPS = [
    django.contrib.admin,
    ...django.contrib.staticfiles,
    corsheaders,#放在新建应用之前
    rest_framework,
    ...crm
]
  • 中间件注册
MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
    corsheaders.middleware.CorsMiddleware,  # 注意顺序,放在此处
    django.middleware.common.CommonMiddleware,
     ...
]
  • 其它设置
CORS_ORIGIN_ALLOW_ALL = True  #允许所有的请求,或者设置CORS_ORIGIN_WHITELIST,二选一
CORS_ALLOW_HEADERS = (*) #允许所有的请求头
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie,前端需要携带cookies访问后端时,需要设置withCredentials: true

这样就可以进行跨域使用了。

  但是大多数站点将需要利用Django提供跨站点请求伪造保护CORS和CSRF是分开的,并且Django无法使用您的CORS配置免除网站Referer对安全请求所做检查。做到这一点的方法是使用其CSRF_TRUSTED_ORIGINS设置

3、CSRF整合

#1、CSRF_TRUSTED_ORIGINS  设置
CORS_ORIGIN_WHITELIST  = [
      http://read.only.com  http://change.allowed.com ,
] #不需要CORS_ORIGIN_ALLOW_ALL=True的设置

CSRF_TRUSTED_ORIGINS  = [
      change.allowed.com ,
]

#2、中间件设置
#启用此功能在django.middleware.csrf.CsrfViewMiddleware后,还应添加#corsheaders.middleware.CorsPostCsrfMiddleware
MIDDLEWARE_CLASSES  = [
     ... 
     corsheaders.middleware.CorsMiddleware ,
     ... 
     django.middleware.csrf.CsrfViewMiddleware corsheaders.middleware.CorsPostCsrfMiddleware ,
     ... 
]

详情参考官方文档https://github.com/adamchainz/django-cors-headers

 

以上是关于碰到的一个跨域问题:自定义header,接口请求不通的主要内容,如果未能解决你的问题,请参考以下文章

再遇CORS -- 自定义HTTP header的导致跨域

Django前后端分离跨域请求问题

获取跨域请求的自定义的response headers

前端请求接口出现的跨域问题

请求接口无响应

[PHP] 再续 Laravel 5.5 接口 跨域问题 终极暴力解决办法