Django跨域请求--CORS
在上一篇文章中DJANGO跨域请求--JSONP已经阐述了为什么我们需要跨域请求,以及跨域方法JSONP。随着技术的发展,现在的浏览器可以主动支持设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
一 CORS基础
1.1 简单请求与复杂请求
条件:
1、请求方式:HEAD、GET、POST
2、请求头信息:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type 对应的值是以下三个中的任意一个
application/x-www-form-urlencoded
multipart/form-data
text/plain
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
1.2 简单请求与复杂请求的区别
简单请求:一次请求
复杂请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
1.3 关于预检
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
1.4 CORS简图
1.5 CORS的优缺点
优点:可以发任意请求
缺点:复杂请求时得先做个“预检”,再发真实的请求,两次请求会有性能上的损耗
二 基于CORS实现AJAX请求
2.1 支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
客户端cors.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>CORS示例</h3>
<button type="button" onclick="getData()" >获取第三方数据</button>
<script src="/static/jquery-3.2.1.js"></script>
<script>
function getData() {
$.ajax({
url:'http://127.0.0.1:8000/cors_data/',
type:'GET',
success:function (arg) {
var $tag = $('<h6>');
$tag.text(arg);
$('h3').append($tag);
}
})
}
</script>
</body>
</html>
第三方服务端views.py
def cors_data(request):
obj = HttpResponse('第三方数据')
obj['Access-Control-Allow-Origin'] = "http://127.0.0.1:8001"
return obj
如果我们对所有的地址都不进行限制,第三方服务端views.py中为:
obj['Access-Control-Allow-Origin'] = "*"
执行结果:
2.2 支持跨域,复杂请求
复杂请求在发送真正的请求前,会先发送一个OPTIONS请求,第三方服务端先”预检“一下,”预检“通过才会发送正式数据。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
- “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age
方式一:请求方式类复杂请求
客户端cors.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>CORS示例</h3>
<button type="button" onclick="getData()" >获取第三方数据</button>
<script src="/static/jquery-3.2.1.js"></script>
<script>
function getData() {
$.ajax({
url:'http://127.0.0.1:8000/cors_data/',
//type:'GET',
type:'PUT', //方式为PUT,为复杂请求
success:function (arg) {
var $tag = $('<h6>');
$tag.text(arg);
$('h3').append($tag);
}
})
}
</script>
</body>
</html>
访问结果:
这里因为为复杂请求,我们需要在后端代码增加一个预检的过程。
第三方服务端views.py
def cors_data(request):
if request.method == 'OPTIONS':
# 预检
obj = HttpResponse()
obj['Access-Control-Allow-Origin'] = " http://127.0.0.1:8001"
obj['Access-Control-Allow-Methods'] = "PUT" #需要设置
return obj
elif request.method == "PUT":
obj = HttpResponse('第三方数据')
obj['Access-Control-Allow-Origin'] = " http://127.0.0.1:8001"
return obj
执行结果:
注意:测试时需要注释掉第三方settings.py中的CSRF
方式二:带有请求头的复杂请求
客户端cors.html中js代码更改如下:
<script>
function getData() {
$.ajax({
url:'http://127.0.0.1:8000/cors_data/',
type:'GET',
headers:{'name':'joe1991'}, //有请求头的复杂请求
success:function (arg) {
var $tag = $('<h6>');
$tag.text(arg);
$('h3').append($tag);
}
})
}
</script>
第三方服务端views.py
def cors_data(request):
if request.method == 'OPTIONS':
# 预检
obj = HttpResponse()
obj['Access-Control-Allow-Origin'] = " http://127.0.0.1:8001"
obj['Access-Control-Allow-Headers'] = 'name' #处理方式不同
# obj['Access-Control-Allow-Methods'] = "PUT"
return obj
else :
obj = HttpResponse('第三方数据')
obj['Access-Control-Allow-Origin'] = " http://127.0.0.1:8001"
return obj
前端访问截图
2.3 跨域获取响应头及跨域传输cookie
请参考:http://www.cnblogs.com/wupeiqi/articles/5703697.html
三 JSONP与CORS的区别简析
JSONP:主要修改在前端部分,后端需做约束修改,发jsonp请求
JSONP:只能发GET请求
CORS:前端的代码不用修改,服务端的代码需要修改
CORS:可以发任意请求,简单请求与复杂请求处理方式不同






浙公网安备 33010602011771号