前言

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

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

   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. AA.Dapper升级了

    AA.Dapper基于dapper进一步封装而成的orm框架,提供增删改查.分页.事务.原生sql的功能,以满足日常的业务开发. 1.Repository层: DapperRepository类包含大 ...

  2. nuget使用经验:复杂依赖关系下的包版本问题

    背景 之前同事问到过1个关于nuget包被多层引用后,最终生效的版本的问题.当时通过在项目中重新安装了一次nuget包解决了. 现在来重新复盘一下当时的场景,顺便把这种场景下nuget处理逻辑分享给大 ...

  3. 蒲公英 · JELLY技术周刊 Vol.25 · Webpack 5 正式发布,你学废了么

    蒲公英 · JELLY技术周刊 Vol.25 阔别两年,Webpack 5 正式发布了,不仅清理掉很多冗余的功能,同样也为我们带来了很多新鲜的能力,不论是默认开启的持久缓存,还是反病毒保护,亦或者被其 ...

  4. nrf528xx bootloader 模块介绍

    1. bootloader 的基本功能: 启动应用 几个应用之间切换 初始化外设 nordic nrf52xxx的bootloader主要功能用来做DFU, 可以通过HCI, UART 或BLE通信的 ...

  5. Jmeter之参数化函数助手__randomstring

    1.Tools->函数助手对话框,选择__Random String,2表示随机生成的字符长度:3表示从哪些字符中随机生成:然后点击生成,得到对应的变量: 5中372表示该函数随机生成的字符串, ...

  6. lumen容器模仿

    <?php class Container { private $bindings = []; private $instances = []; public function getClosu ...

  7. Linux如何在vim里搜索关键字

    例如搜索 the写法:/the     +回车 /+关键字 ,回车即可.此为从文档当前位置向下查找关键字,按n键查找关键字下一个位置: ?+关键字,回车即可.此为从文档挡圈位置向上查找关键字,按n键向 ...

  8. JavaSE学习笔记04方法、数组

    1.方法 java方法是语句的集合,它们在一起执行一个功能 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 设计方法的原则:一个方法只完成1个功能,这样 ...

  9. Linux基础命令之.命令

    . 点命令 .命令等同source 可以让配置文件被读到进程中,立刻生效

  10. 请勿过度依赖Redis的过期监听!!

    作者:迪壳 https://juejin.im/post/6844904158227595271 Redis 过期监听场景 业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭 ...