跨域
只要协议、域名、端口有一项不同,都被当做是不同的源。
同源策略以源为边界,把资源分隔开,从而保护用户的信息安全。
JSONP
jsonp不是ajax请求,ajax是异步的,jsonp是同步的。
用于解决AJAX跨域的一种方案。
用jquery实现JSONP:
|
|
完整的请求:
http://tonghuashuo.github.io/test/jsonp.txt?callback=dosomething&_=1471419449018。
三个参数:
- dataType: ‘jsonp,用于表示这是一个jsonp请求
- jsonp:’callback’,用于告诉服务器根据这个参数获取回调函数的名称,通常约定就为
callback
。 - jsonpCallback:’dosomthing’,回调函数的名称,也是callback参数的值
其中:
(1)jsonpCallback参数可以忽略,jquery会随机生成一个字符串作为函数名,推荐这么做,以减少不必要的命名,同时派出潜在的安全隐患。忽略jsonpCallback的同时,jsonp参数必须指明,不能为false。
|
|
(2)jquery还支持将jsonp设置为false来避免callback出现在请求URL中,但需要前后端配合,前端必须要指定jsonpCallback的值为一个函数名,后端由于无法从请求中获取回调函数的名称,因此也必须固定使用同名的字符串进行拼接。
|
|
后台:从数据库获取请求的资源,构造JSON形式的返回内容–>根据url中的callback参数书的值,以字符串凭借的方式,构造出一个“javaScript函数调用”的字符串。将准备返回的json作为参数放入括号中。
前端:响应内容传回前端时,jquery会自动接管,将其中的json部分玻璃出来给success
和error
。
纯javaScript实现jsonp
|
|
jsonp的原理
ajax受到“同源政策”的限制,但是带有src
的<script>
、<img>
、<iframe>
是不受限制的。因此我们可以通过向页面中动态添加<script>
标签来完成对跨域资源的访问。
jsonp的优缺点
优点:
兼容性好,较老的浏览器上也可以使用。
缺点:
1、只能进行GET
请求,不能进行POST
请求,因为是通过<script>
引用的资源,参数全部显示的放在URL中,和ajax没有关系。
2、存在安全隐患,动态插入<script>
标签其实就是一种脚本注入。
子域不同主域相同(document.domain
)
一个页面地址为http://www.damonare.cn/a.html
,他的页面里面有一个iframe,它的src为http://damonare.cn/b.html
。
这个页面与它里面的iframe看框架是不同的域,所以无法通过在页面中书写js代码来获取iframe中的东西。
解决办法:
利用document.domain
,把两个页面的document.domain
都设成相同的域名。但document.domain
的设置有限制,只能把document.domain
设置成自身或更高一级的父域,且主域必须相同。
- 在页面http://www.damonare.cn/a.html 中设置document.domain:
|
|
- 在页面http://damonare.cn/b.html 中也设置document.domain:
|
|
通过CORS跨域
实现CORS通信的关键是服务器,服务期实现了CORS接口,就可以跨域通信。
服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。
CORS与JSONP对比:
- JSONP只能进行GET请求,而CORS支持所有类型的HTTP请求;
- JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
通过HTML5的postMessage方法跨域
主要使用接受信息的message
和发送信息的postMessage
方法。
比如aa.cn
域的A页面通过iframe
嵌入一个google.com
域的B页面,可以通过这一方法通信。
A页面通过potMessage发送消息:
|
|
ifr
:表示目标窗口;hello, world!
:要发送的消息,类型为String、Object- targetOrigin: 限定的消息发送范围,不限制时使用*
B页面通过message
事件监听并接受消息:
|
|
window.name + iframe
设置了window.name
,即使页面用location.href
实现了跳转,这个window.name
还是会保留。
用$(iframe).contentWindow
来拿到iframe
中的window
对象,属性会很少,但如果外面的域和iframe
的域相同时,这个ifram
就是window
的完整对象,就可以访问它的所有属性。
应用:
|
|