一、什么是跨域
跨域是指从一个域名的网页去请求另一个域名的资源。
只要协议、域名、端口有任何一个不同,就是不同的域。
浏览器的同源策略
同源是指:协议、域名和端口都相同
浏览器在执行脚本前,会先检查脚本是否同源,只有同源脚本才会被执行。
同源策略是浏览器最核心也是最基本的安全功能。用于防御跨站脚本攻击。
浏览器对script、img等没有跨域限制。
二、跨域的几种方法
1. 跨域资源共享CORS
CORS是一个W3C标准。
基本思想是使用自定义的HTTP头部,让服务器能声明哪些来源可以通过浏览器访问该服务器上的资源。
服务端响应头设置:1
2
3
4
5Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials
客户端只需要正常发送请求。注意跨域请求默认不携带cookie信息,需要设置1
xhr.withCredentials = true;
关于CORS的详细说明:阮一峰:跨域资源共享CORS详解
2. jsonp跨域
jsonp依赖的根据是浏览器的同源策略对script没有限制。
先来看一个例子:
A客户端要请求B服务器的data:
A客户端:1
2
3
4
5
6<script type="text/javascript">
function handleResponse(data){
// 处理data
}
</script>
<script src="http://domainB.com/data.php?callback=handleResponse"></script>
B服务端(data.php):1
2
3
4
5
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
B服务端data.php输出结果为:1
handleResponse(['a','b','c'])
A客户端加载1
<script src="http://domainB.com/data.php?callback=handleResponse"></script>
完成后,会执行之前定义的handleResponse(data)方法,并且把数据([‘a’,’b’,’c’])传入。
这样就达到了我们想要获取B服务端数据的目的。
- 优点:兼容性好
- 缺点:只支持get请求。
3. 代理
同源策略是浏览器的,服务器没有该限制。所以可以通过服务器来解决跨域问题。
A Client ===> A Server ===> B Server ===> A Client4.document.domain+iframe
浏览器的同源策略限制了浏览器中不同域的框架之间是不能进行js交互操作的。
父窗口(http://www.example.com/a.html):1
2
3
4
5
6
7
8
9<script type="text/javascript">
function test(){
var iframe = document.getElementById('ifame');
var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的
var doc = win.document;//这里获取不到iframe里的document对象
var name = win.frameName;//这里同样获取不到子页面中的属性
}
</script>
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
子窗口(http://example.com/b.html):1
2
3<script type="text/javascript">
var frameName = "child";
</script>
跨域方法:两个页面都通过js设置example.com为主域,就实现了同域1
document.domain = 'example.com';
5.window.postMessage
这是html5的新特性,window.postMessage() 方法被调用时,会在页面的所有脚本执行完毕之后( 在该方法之后设置的事件、之前设置的timeout 事件,等等)向目标窗口派发一个 MessageEvent 消息。
MessageEvent消息有四个属性需要注意: message 属性表示该message 的类型; data 属性为 window.postMessage 的第一个参数;origin 属性表示调用window.postMessage() 方法时调用页面的当前状态; source 属性记录调用 window.postMessage() 方法的窗口信息。
详细介绍MDN
注意:
为了安全:
- 用于接收消息的任何事件监听器必须首先使用origin和source属性来检查消息的发送者的身份
- 当使用postMessage将数据发送到其他窗口时,始终指定精确的目标origin,而不是*
- 如果不希望从其他网站接收message,就不要为message事件添加任何事件侦听器
6.websocket
也是html5的新特性。没有同源限制,客户端可以与任意服务器通信。
阮一峰:websocket教程
参考:
https://segmentfault.com/a/1190000000718840
http://blog.csdn.net/ligang2585116/article/details/73072868?locationNum=13&fps=1