1.同源策略又名同域策略,就是(主机名+协议+端口号【若存在】)三者相同。也就是说javascript只能够操做本身域下的东西,不能操做其余域下的东西。好比百度下javascript是不可操做谷歌下的页面;javascript
在浏览器中,<script>、<img>、<iframe>、<link>等标签均可以加载跨域资源,而不受同源限制,但浏览器限制了JavaScript的权限使其不能读、写加载的内容。css
同源策略只对网页的HTML文档作了限制,对加载的其余静态资源如javascript、css、图片等仍然认为属于同源。html
2.使用ajax必须知足同源策略;在本地hosts文件配置两个域名访问IP做为测试用java
127.0.0.1 www.fwd.com
127.0.0.1 www.khd.compython
在 http://www.khd.com:8002/khd 文件里用ajax请求http://www.fwd.com:8001/fwd(jquery)jquery
请求页面(jquery):web
<input type="button" value="提交" onclick="doajax();"/>
<script>
function doajax() {
$.ajax({
url: 'http://www.fwd.com:8001/fwd',
type: 'POST',
data:{'k1':'v1'},
success: function (responseText, statusText) {
},
error: function (event, errorText, errorType) {
}
});
}
</script>
此时点击按钮发起ajax请求后,能够看到请求已被浏览器的同源策略阻止。
3. 突破浏览器同源策略ajax跨域请求,有两个办法:ajax
法1、JSONP方式json
自定义JSONP跨域请求数据只能是get方法的请求,也就是利用script标签和script标签的src发送get请求跨域
1在要请求数据的页面用js建立一个script标签,src等于要请求数据的地址
2响应页面返回的必须是一个带有参数的函数名称
3自定义对应响应页面返回的函数,这样自定义的函数也就会执行了,就能获得数据
请求页面(原生js):
<input type="button" value="跨域提交" onclick="doajax();"/> <script> //利用原生js本身建立一个跨域请求 function doajax() { //当点击提交按钮是执行函数 var tag = document.createElement('script'); //建立一个script标签 tag.src = 'http://www.fwd.com:8001/fwd'; //设置script标签的src地址,为要请求数据的地址,由于src是不受同源策略 document.head.appendChild(tag); //将script标签添加到head标签里面 document.head.removeChild(tag); //添加后会当即发送请求,因此这里能够将添加的script标签删除了 } //响应网站返回,shuju({'k1':'v1'}); 也就至关于返回了一个带有参数的函数名称 function shuju(shj) { //自定义执行函数,和响应网站返回的名称相同,参数就是响应网站返回的数据 for(var i in shj){ //循环响应网站返回的数据 alert(i + ':' + shj[i]); //打印出数据的键和值,v1:k1 } } </script>
响应页面:
class fwdHandler(tornado.web.RequestHandler):
def get(self): #接收get请求
# self.render("fwd.html")
self.write("shuju({'k1':'v1'});") #返回的数据
def post(self):
self.write("post请求成功")
ajax的JSONP方式:
ajax跨域请求本质上就是上面自定义跨域的方式,只不过ajax帮咱们封装好了,不用咱们去建立script标签
请求页面(jquery):
<input type="button" value="跨域提交" onclick="doajax();"/> <script> function doajax() { //当点击提交按钮是执行函数 $.ajax({ type: 'GET', url: 'http://www.fwd.com:8001/fwd', dataType: 'jsonp', //JSONP,数据类型 jsonpCallBack:'shj' //接收响应页面带有参数的函数名称,shj来自响应端 }); } //响应网站返回,shuju({'k1':'v1'}); 也就至关于返回了一个带有参数的函数名称 function shuju(shj) { //自定义执行函数,和响应网站返回的名称相同,也就会执行自定义函数,而参数就是响应网站返回的数据 for (var i in shj) { //循环响应网站返回的数据 alert(i + ':' + shj[i]); //打印出数据的键和值 } } </script>
响应端:
class fwdHandler(tornado.web.RequestHandler): def get(self): #接收get请求 # self.render("fwd.html") self.write("shuju({'k1':'v1'});") #返回数据 def post(self): self.write("post请求成功")
法2、基于CORS实现跨域Ajax
请求页面不变,响应端返回数据的时候带有响应头标识,告诉浏览器容许跨域请求。
响应端:
class fwdHandler(tornado.web.RequestHandler):
def get(self): #接收get请求
pass
def post(self):
self.set_header('Access-Control-Allow-Origin','*')
self.write("{'k1':'v1'}") # 返回数据
跨域传输cookie(跨域请求中,默认HTTP Authentication信息,Cookie头以及用户的SSL证书都是不会被发送):
请求页面(jquery):
xhrFields:{withCredentials: true}, //传递Cookie头以及用户的SSL证书
响应端(python):
class fwdHandler(tornado.web.RequestHandler): def get(self): #接收get请求 pass def options(self): #接收预检的options请求 self.set_header('Access-Control-Allow-Credentials', "true") #传递Cookie头以及用户的SSL证书 self.set_header('Access-Control-Allow-Origin', 'http://www.khd.com:8002') #预检请求或者数据请求时容许跨域,容许跨域的域名 self.set_header('Access-Control-Allow-Methods', 'PUT') #预检请求时容许请求页面的请求方式跨域,容许跨域的请求方式(多个逗号隔开) self.set_header('Access-Control-Allow-Headers', "k1,k2") #预检请求时容许请求页面ajax设置请求头headers属性跨域,容许跨域的headers属性请求头(多个逗号隔开) def put(self): self.set_header('Access-Control-Allow-Credentials', "true") # 传递Cookie头以及用户的SSL证书 self.set_header('Access-Control-Allow-Origin','http://www.khd.com:8002') self.write("{'k1':'v1'}") # 返回数据 self.set_cookie('kkkkk', 'vvvvv') #写入cookie print(self.get_cookie('kkkkk')) #获取cookie