CORS
随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
**index.html **
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'jquery-3.2.1.js' %}"></script>
</head>
<body>
<h1>维基解密</h1>
<script>
$.ajax({
url: "http://127.0.0.1:8000/get_data/",
type: 'GET',
success: function(data){
console.log(data);
}
})
</script>
</body>
</html>
views.py
def data(request):
return HttpResponse("机密数据")
前端结果
这里提示我们缺少一个请求头所以我们在views中将这个请求头带上
views.py
def data(request):
response = HttpResponse("机密数据")
response['Access-Control-Allow-Origin'] = " http://127.0.0.1:8888"
return response
这里我们只是将127.0.0.1:8888这个地址的请求可以跨域进行访问,也可以对所有的都不现在即:
response['Access-Control-Allow-Origin'] = "*“
二、简单请求 OR 非简单请求
条件:
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
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
实例:PUT请求
**index.html **
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'jquery-3.2.1.js' %}"></script>
</head>
<body>
<h1>维基解密</h1>
<script>
$.ajax({
url: "http://127.0.0.1:8000/get_data/",
type: 'PUT', //这是一个复杂请求
success: function(data){
console.log(data);
}
})
</script>
</body>
</html>
我们查看发送到请求头信息如下:
这里因为是复杂请求所以我们需要在后端代码增加一个预检的过程
views.py
def data(request):
if request.method == "OPTIONS":
# 预检
response = HttpResponse()
response['Access-Control-Allow-Origin'] = "*"
response['Access-Control-Allow-Methods'] = "PUT"
return response
elif request.method == "PUT":
response = HttpResponse("机密数据")
response['Access-Control-Allow-Origin'] = "*"
return response
再看前端的页面:
带有请求头的复杂请求
index.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'jquery-3.2.1.js' %}"></script>
</head>
<body>
<h1>维基解密</h1>
<script>
$.ajax({
url: "http://127.0.0.1:8000/get_data/",
type: 'GET',
headers:{'xxx':666},
success: function(data){
console.log(data);
}
})
</script>
</body>
</html>
前端渲染页面显示:
跨域传输cookie
在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。
-
浏览器端:XMLHttpRequest的withCredentials为true
-
服务器端:Access-Control-Allow-Credentials为true
-
注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 *
index.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="submit" onclick="XmlSendRequest();" />
</p>
<p>
<input type="submit" onclick="JqSendRequest();" />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
}
};
xhr.withCredentials = true;
xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
}
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
xhrFields:{withCredentials: true},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
views.py
class MainHandler(tornado.web.RequestHandler):
def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Credentials', "true")
self.set_header('xxoo', "seven")
self.set_header('bili', "daobidao")
self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
self.set_cookie('kkkkk', 'vvvvv');
self.write('{"status": true, "data": "seven"}')
def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10)