前言

   在前后端分离项目中,如何解决跨域请求是一个必须要面对的问题。因为前端和后端的数据交互会被浏览器的同源策略所挟持,在很早之前我在博客园发了一篇文章,大概就说了一下如何简单粗暴的解决跨域。

   其实那种解决办法是不适用于内部项目的,而是对一些公共的开发接口做访问进行数据获取,下面是文章链接:

   jQuery JSONP解决跨域请求

CORS

   CORS就是跨域资源共享的意思,它需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

   整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

   因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

基本流程

   浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。 浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

请求区别

   只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求。

  1. 请求方法是以下三种方法之一:

       HEAD GET POST

  1. HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

处理情况

   浏览器对于上面两种请求处理,会有不一样的方式:

   简单请求

   浏览器只会发送一次请求,然后后端将会返回数据,此时后端如果没有做跨域资源请求的允许,数据将会被浏览器同源策略所拦截。

   非简单请求

   浏览器会发送两次请求,第一次请求方式为OPTIONS,大概就是做一个预检查,检查后端是否允许第二次请求的发送。

   如果允许,才会发送第二次请求,后端会将第二次请求的数据返回,如果后端没有做跨域资源请求的允许,数据将会被浏览器同源策略所拦截。

   如果不允许,浏览器就不会发送第二次请求。

后端解决

   对于简单请求来说,我们只需要允许跨域资源共享即可。

   所以只需要在后端设置一个请求头:

Access-Control-Allow-Origin = "域名或者*"

   对于非简单请求来说,我们需要让预检进行通过,此外还需要允许跨域资源共享,所以需要设置最少设置两个或多个请求头:

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
# 这两个是让预检通过
Access-Control-Allow-Headers = "Content-Type"
Access-Control-Allow-Headers = "authorization" #JWT认证 # 下面这个是允许资源共享
Access-Control-Allow-Origin = "域名或者*"

基本总结

   一言以蔽之,当前端跨域向后端发送、请求数据时,有可能发简单请求,也有可能发非简单请求。

   简单请求只会发一次,而非简单请求会发两次请求。

   如果是简单请求,数据就会直接返回,如果是非简单请求,则需要后端做出一些相应的设置才会允许第二次真正请求的发送。

   对于非简单请求的预检来说,它其实是规定了前端能够去使用哪些请求方式,如GET/POST,同时还允许请求头中有什么,如Content-Type以及JWT随机字符串。

   我举个例子,如果前端要跨域通过POST请求发送一个JSON数据那么它的流程如下:

    1. 发送OPTIONS请求进行预检,检测是否允许带有Content-Type请求头(因为JSON格式必须由该请求头声明)
    2. 预检通过后,发送POST请求,Content-TypeJSON,带上数据发送过去。

Django解决

中间件

   对于Django来说,我们可以将处理设置在中间件中。不管你是使用drf还是原生Django,都可以这样设置,因为此时的request对象并未被包装。

   下面是同时支持简单请求和非简单请求的示例:

from django.utils.deprecation import MiddlewareMixin

class CorsMiddle(MiddlewareMixin):
def process_response(self, request, response):
response['Access-Control-Allow-Origin'] = '*' # 允许跨域,解决同源策略。简单和非简单请求都需要设置这个
if request.method == "OPTIONS":
# 可以加*,代表允许所有。 这里是预检的OPTIONS请求,它允许Content-Type请求头和authorization请求头。
response["Access-Control-Allow-Headers"] = "Content-Type" #
response["Access-Control-Allow-Headers"] = "authorization" return response # 记得在setting的中间件中配置

django-cors-headers

   这是一个模块,可以很好的解决同源策略问题,以及非简单请求的预检问题。

   下载安装即可:

pip install django-cors-headers

   然后需要进行注册:

INSTALLED_APPS = (
'corsheaders',
)

   添加中间件(其实它的解决方案和上面写的思路完全一模一样):

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware', # 写上面,因为Django中间件的返回顺序是自下而上。
...
]

   在settings.py中进行配置:

CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True # 允许异端请求,解决同源策略 CORS_ORIGIN_WHITELIST = (
'*'
)
CORS_ALLOW_METHODS = ( # 允许的请求方式
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
) CORS_ALLOW_HEADERS = ( # 允许的请求头
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)

CORS与Django的更多相关文章

  1. Django框架12 /同源、跨域、CORS

    Django框架12 /同源.跨域.CORS 目录 Django框架12 /同源.跨域.CORS 1. 同源策略 2. 跨域 3. 解决跨域:CORS/跨域资源共享 1. 同源策略 同源策略(Same ...

  2. python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确.方便快速开发 - 针对pc,手机,ipad,微信,支付宝... 使用同一个接口 2. 简述http协议? - 基 ...

  3. 1220 Vue与Django前后端的结合

    目录 vue的安装 Vue前端的设置 页面的分布 后台数据的替换 css样式 Django的配置 国际化配置 axios插件安装 CORS跨域问题(同源策略) 处理跨域问题: cors插件 axios ...

  4. 01-vue和api整合流程、CORS

    1.后端代码 1.项目结构 2.项目代码 主url from django.contrib import admin from django.urls import path, include url ...

  5. Django框架(二十九)—— 跨域问题

    目录 跨域问题 一.同源策略 二.CORS(跨域资源共享) 三.CORS两种请求(简单请求与非简单请求) 1.简单请求(一次请求) 2.非简单请求(两次请求) 四.CORS在Django中的应用 1. ...

  6. 异步请求之ajax

    一.初识ajax 1.下载引入jQuery <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"& ...

  7. 跨域AJAX

    本篇主要讨论JSONP和CORS这两种技术,使用它们的原因是为了完成对资源的跨域访问,也就是如何绕过浏览器的同源策略Same-origin Policy. 那么什么是Same-origin Polic ...

  8. 七、Ajax请求

    七.Ajax请求 客户端(浏览器)向服务端发起请求的形式: 地址栏:GET 超链接标签:GET form表单:GET或POST Ajax(重要):GET或POST或PUT或DELETE AJAX(As ...

  9. tornado django flask 跨域解决办法(cors)

    XMLHttpRequest cannot load http://www.baidu.com. No 'Access-Control-Allow-Origin' header is present ...

随机推荐

  1. java流程控制学习

    Java流程控制 计算的步骤就是算法. 1.用户交互Scanner next()不能得到带有空格的字符串.[它是以空格为结束符]nextline()可以,[它是以回车为结束符] 2.顺序结构 从上到下 ...

  2. sop服务治理

    一,为什么需要服务治理: 我们最先接触的单体架构, 整个系统就只有一个工程, 打包往往是打成了 war 包, 然后部署到单一 tomcat 上面, 这种就是单体架构, 如图: 假如系统按照功能划分了, ...

  3. day03 Pyhton学习

    昨日回顾 1.while循环 语法 while 条件: 语句 else: 语句 执行语句:判断语句是否为真.如果真,执行循环,然后再次判断条件,如果不满足执行else语句. break 结束循环 co ...

  4. lumen-ioc容器测试 (1)

    lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...

  5. thinkpad怎么设置u盘启动

    1.按下笔记本的开机键,当屏幕出现"Press F1 for ThinkPad BIOS Setup Utility"提示时,迅速按下f1键,此时系统就自动进入到ThinkPad的 ...

  6. linux(CentOS7)_离线_mysql安装

    注意:本文系统环境 CentOS 7.7 64位 MySQL Community Server 5.7.32 一丶卸载CentOS7系统中默认的数据库mariadb 原因一:ps原作者的话介绍下背景: ...

  7. js堆排序

    堆的预备知识 堆是一个完全二叉树. 完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点). 大顶堆:根结点为最大值,每个 ...

  8. mysql 必会基础2 distinct

    1.插入数据方式 a> insert into student (id, name, age) values (1, 'zhangsan', 3); --字符串类型要用双引号.或单引号引起来,否 ...

  9. jenkins自动拉取git分支构建项目

    一,创建jenkins项目 new item ->freestyle project, 自定义一个项目名称 二,配置项目 1,Source Code Management 选择 git,输入gi ...

  10. ubuntu 16.04 Chrome

    打开终端 输入 命令1:sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list ...