CORS与Django
前言
在前后端分离项目中,如何解决跨域请求是一个必须要面对的问题。因为前端和后端的数据交互会被浏览器的同源策略所挟持,在很早之前我在博客园发了一篇文章,大概就说了一下如何简单粗暴的解决跨域。
其实那种解决办法是不适用于内部项目的,而是对一些公共的开发接口做访问进行数据获取,下面是文章链接:
CORS
CORS
就是跨域资源共享的意思,它需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS
通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS
通信与同源的AJAX
通信没有差别,代码完全一样。浏览器一旦发现AJAX
请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS
通信的关键是服务器。只要服务器实现了CORS
接口,就可以跨源通信。
基本流程
浏览器将CORS
请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。 浏览器发出CORS
简单请求,只需要在头信息之中增加一个Origin
字段。 浏览器发出CORS
非简单请求,会在正式通信之前,增加一次HTTP
查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP
动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
请求区别
只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求。
请求方法是以下三种方法之一:
HEAD GET POST
- 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
数据那么它的流程如下:
- 发送
OPTIONS
请求进行预检,检测是否允许带有Content-Type
请求头(因为JSON
格式必须由该请求头声明) - 预检通过后,发送
POST
请求,Content-Type
为JSON
,带上数据发送过去。
- 发送
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的更多相关文章
- Django框架12 /同源、跨域、CORS
Django框架12 /同源.跨域.CORS 目录 Django框架12 /同源.跨域.CORS 1. 同源策略 2. 跨域 3. 解决跨域:CORS/跨域资源共享 1. 同源策略 同源策略(Same ...
- python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确.方便快速开发 - 针对pc,手机,ipad,微信,支付宝... 使用同一个接口 2. 简述http协议? - 基 ...
- 1220 Vue与Django前后端的结合
目录 vue的安装 Vue前端的设置 页面的分布 后台数据的替换 css样式 Django的配置 国际化配置 axios插件安装 CORS跨域问题(同源策略) 处理跨域问题: cors插件 axios ...
- 01-vue和api整合流程、CORS
1.后端代码 1.项目结构 2.项目代码 主url from django.contrib import admin from django.urls import path, include url ...
- Django框架(二十九)—— 跨域问题
目录 跨域问题 一.同源策略 二.CORS(跨域资源共享) 三.CORS两种请求(简单请求与非简单请求) 1.简单请求(一次请求) 2.非简单请求(两次请求) 四.CORS在Django中的应用 1. ...
- 异步请求之ajax
一.初识ajax 1.下载引入jQuery <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"& ...
- 跨域AJAX
本篇主要讨论JSONP和CORS这两种技术,使用它们的原因是为了完成对资源的跨域访问,也就是如何绕过浏览器的同源策略Same-origin Policy. 那么什么是Same-origin Polic ...
- 七、Ajax请求
七.Ajax请求 客户端(浏览器)向服务端发起请求的形式: 地址栏:GET 超链接标签:GET form表单:GET或POST Ajax(重要):GET或POST或PUT或DELETE AJAX(As ...
- tornado django flask 跨域解决办法(cors)
XMLHttpRequest cannot load http://www.baidu.com. No 'Access-Control-Allow-Origin' header is present ...
随机推荐
- java流程控制学习
Java流程控制 计算的步骤就是算法. 1.用户交互Scanner next()不能得到带有空格的字符串.[它是以空格为结束符]nextline()可以,[它是以回车为结束符] 2.顺序结构 从上到下 ...
- sop服务治理
一,为什么需要服务治理: 我们最先接触的单体架构, 整个系统就只有一个工程, 打包往往是打成了 war 包, 然后部署到单一 tomcat 上面, 这种就是单体架构, 如图: 假如系统按照功能划分了, ...
- day03 Pyhton学习
昨日回顾 1.while循环 语法 while 条件: 语句 else: 语句 执行语句:判断语句是否为真.如果真,执行循环,然后再次判断条件,如果不满足执行else语句. break 结束循环 co ...
- lumen-ioc容器测试 (1)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- thinkpad怎么设置u盘启动
1.按下笔记本的开机键,当屏幕出现"Press F1 for ThinkPad BIOS Setup Utility"提示时,迅速按下f1键,此时系统就自动进入到ThinkPad的 ...
- linux(CentOS7)_离线_mysql安装
注意:本文系统环境 CentOS 7.7 64位 MySQL Community Server 5.7.32 一丶卸载CentOS7系统中默认的数据库mariadb 原因一:ps原作者的话介绍下背景: ...
- js堆排序
堆的预备知识 堆是一个完全二叉树. 完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点). 大顶堆:根结点为最大值,每个 ...
- mysql 必会基础2 distinct
1.插入数据方式 a> insert into student (id, name, age) values (1, 'zhangsan', 3); --字符串类型要用双引号.或单引号引起来,否 ...
- jenkins自动拉取git分支构建项目
一,创建jenkins项目 new item ->freestyle project, 自定义一个项目名称 二,配置项目 1,Source Code Management 选择 git,输入gi ...
- ubuntu 16.04 Chrome
打开终端 输入 命令1:sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list ...