同源策略
同源的定义
如果两个页面的协议、端口、主机都相同,则两个页面具有相同的源。
下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例:
| URL | 结果 | 原因 |
| ————————————— | —- | ———————— |
| http://a.xyz.com/dir2/other.html | 成功 |
| http://a.xyz.com/dir/inner/another.html | 成功 |
| https://a.xyz.com/secure.html | 失败 | 不同协议 ( https和http ) |
| http://a.xyz.com:81/dir/etc.html | 失败 | 不同端口 ( 81和80) |
| http://a.opq.com/dir/other.html | 失败 | 不同域名 ( xyz和opq) |
同源策略是什么
同源策略是一种预定,是由NEtscape提出的著名安全策略。他是浏览器最核心、最基本的安全功能。
不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以xyz.com下的js脚本采用ajax读取abc.com里面的文件数据是会被拒绝的。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
不受同源策略限制的
- 页面中的链接、重定向以及表单提交
- 跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的
<script src="..."></script>,<img>,<link>,<iframe>等。
跨域
为什么要跨域
比如某视频网站由于数据太多,分布在了不同的服务器上,所以需要突破同源策略,实现数据交互。
跨域的实现
jsonp请求
jsonp的原理是利用<script>标签的跨域特性,可以不受限制地从其他域中加载资源,类似的标签还有<img>.1
2
3
4
5
6
7
8
9
10
11
12
13<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://zz.zzs7.top/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
(降域)document.domain
同源策略认为域和子域属于不同的域。
比如https://zz.zzs7.top和https://s7.zzs7.top。虽然都属于zzs7.top域名的子域名,但是他们属于不同域。
<script>
document.domain = 'zzs7.top';
// 获取父窗口中变量
</script>
这种方式用在主域名相同子域名不同的跨域访问中
注:可以进行降域,不能升域。
window.name
window的name属性有个特征:在一个窗口(window)的生命周期内,窗口载入的所有的⻚面都是共享一个window.name的,每个⻚面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有⻚面中的,并不会因新⻚面的载入而进行重置。
window.postMessage
window.postMessages是html5中实现跨域访问的一种新方式,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。
可用于解决:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
postMessage(data,origin)方法接受两个参数
- data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
- origin: 协议+主机+端口号,也可以设置为”*”,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/“。
CORS
CORS背后的基本思想,就是使用自定义的HTTP头部,发出XMLHttpRequest请求,让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是应该失败。
详细见CORS跨域资源共享
Web Sockets
web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。