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 ...
随机推荐
- 【题解】Bzoj3916
字符串\(Hash\). 笔者实在太菜了,到现在还没有熟练掌握\(Hash\),就来这里写一篇学习笔记. \(Description\) 有三个好朋友喜欢在一起玩游戏,\(A\)君写下一个字符串\(S ...
- 正则表达式查找“不包含XXX字符串”
使用 当我要找到不包含某些字符串(如test)时, 可以使用 # 独立使用 (?!test). # 加头尾判断 ^((?!test).)*$ 原理 正则表达式的断言功能: (?=pattern) 非获 ...
- juc包:使用 juc 包下的显式 Lock 实现线程间通信
一.前置知识 线程间通信三要素: 多线程+判断+操作+通知+资源类. 上面的五个要素,其他三个要素就是普通的多线程程序问题,那么通信就需要线程间的互相通知,往往伴随着何时通信的判断逻辑. 在 java ...
- 1.入门篇十分钟了解Spring Cloud
文章目录 Spring Cloud入门系列汇总 为什么需要学习Spring Cloud 什么是Spring Cloud 设计目标与优缺点 设计目标 优缺点 Spring Cloud发展前景 整体架构 ...
- RESTfull是什么
经常做接口测试,会看很多接口文档,那怎么识别研发的接口设计是否足够规范,是否符合一些行业标准或准则.那认识了解RESTfull,可以让我们更具有专业性.让我们对接口文档的阅.接口合理性设计识别,做到有 ...
- windows上启动docker容器报错:standard_init_linux.go:211: exec user process caused “no such file or directory” - Docker
解决方案: standard_init_linux.go:190: exec user process caused "no such file or directory" - D ...
- 关于IPA文件重签名后如何跟踪管理APP的技术探讨和实践演示
前言:开发iOS的朋友都知道,在功能开发完成后,我们就会用申请的苹果账号在后台做证书配置,然后提交到AppStore,但是也有部分APP我们不需要提交到AppStore,比如内部测试用的APP.定制给 ...
- const、define 和 static 的区别
目录 define.const static define.const 在 C++ 中,const 和 define 都可以用来定义常量.但是这二者之间有很大的区别: define 的作用 用 def ...
- 多测师讲解requests __上_高级讲师肖sir
1.三种接口接口请求方式 # # 在python当中接口的请求方式有哪些:# import requests # 导入requests接口库# # # # 请求方式有三种:# # # # 第一种:# ...
- 题解:CF593D Happy Tree Party
题解:CF593D Happy Tree Party Description Bogdan has a birthday today and mom gave him a tree consistin ...