环境:python3.6.2+Django1.11.5+pycharm2017.2.3
首先了解什么是浏览器同源策略?
1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。
最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同":
- 协议相同
- 域名相同
- 端口相同
不受浏览器同源策略影响的有,img,script,iframe,它们通过其src属性去请求数据,绕过浏览器同源策略,
所以,ajax也受限,但有些时候,我们不得不做一些手脚来达到ajax跨域请求操作,那么,就用到jsonp和cors了。
注意:cors和jsonp依赖于jquery,使用之前需要导入jquery。
jsonp方式:
我们在client端向server端发送一个普通的ajax请求,结果,会报一个:Access-Control-Allow-Origin的错误,但我们查看server端,是已经反回了,只是数据被浏览器拦截了,那么我们利用script的src的属性进行请求,
我们手动创建一个script标签, 传递URL,定义发送函数和接收变量的函数,但仅仅是这样的话,不做其他操作的话,会报错:数据未定义,因为,通过script请求过来的数据,会按照script的规则当做变量进行定义,所以,数据被script当做变量,导致报错
那么,知道如何报错,我们就手动给变量定义,callback=func,但是,这要server端配合对数据进行配合,不够灵活,因为两边的callback都要一致,client端变一下callback,还要告诉server端同步更改,为了解决这个,我们对server端更改代码,如示例所示,获取到client端的callback,再进行字符串格式化,这样,我们做好如此更改,不管client传什么,我们就可以一劳永逸了
这样,我们手动的实现了jsonp的原理
For exampl:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>ajax跨域之jsonp</h1> <input type="button" id="b1" value="向自己家发送请求"> <input type="button" id="b2" value="向别的网址发送请求"> <input type="button" id="b3" value="手动实现jsonp本质"> <input type="button" id="b4" value="手动实现jsonp本质callback"> <input type="button" id="b5" value="ajax的jsonp,自己写同名回调函数"> <input type="button" id="b6" value="ajax的jsonp,一切从简"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> // 向自己家发送请求没问题, $("#b1").click(function () { $.ajax({ url: 'http://127.0.0.1:8844/test1/', type: 'GET', success: function (arg) { alert(arg) } }) }); // 咱们向别的网址发送请求就会遇到问题,浏览器同源策略影响 $("#b2").click(function () { $.ajax({ url: 'http://127.0.0.1:8033/data/', type: 'GET', success: function (arg) { alert(arg) } }) }); /* jsonp的的本质,利用script标签的src属性发送请求 script的src属性把返回的数据当成一个未定义的变量,所以,我们还要对这个变量做处理 */ $("#b3").click(function () { var tag = document.createElement('script'); tag.src = 'http://127.0.0.1:8033/data2/'; document.head.appendChild(tag) }); // 利用自定义函数来获取返回的数据 function list(arg) { alert(arg); document.head.removeChild(tag) } $("#b4").click(function () { tag = document.createElement('script'); tag.src = 'http://127.0.0.1:8033/data3/?callback=list'; document.head.appendChild(tag) }); // ajax的jsonp,这两种方式,差不多,请求的网站只需动态加上回调函数 //方式一,在自定义的同名回调函数里处理数据,虽然success里也可以处理 function dict(arg) { alert(arg); } $("#b5").click(function () { $.ajax({ url: 'http://127.0.0.1:8033/data5/', type: 'GET', dataType:'JSONP', // 传输方式是jsonp jsonp:'callback', // 等于在地址栏后面加上:?callback jsonpCallback:'dict', // 等于http://127.0.0.1:8033/data4/?callback=dict }) }); // 方式二,一切从简,直接在ajax的success里处理数据 // 要是单独只说明datatype,则ajax会自己定义callback,但是所请求的网站包含数据的函数名,不能写死 // 需写动态的,因为ajax的callback是动态的, $("#b6").click(function () { $.ajax({ url: 'http://127.0.0.1:8033/data5/', type: 'GET', dataType:'JSONP', success: function (arg) { alert(arg) } }) }); </script> </body> </html>