说策略前, 先简单说下一个源的定义.
同源: 如果协议,端口(如果指定了一个)和域名对于两个页面是相同的,则两个页面具有相同的源。
例如下边这个地址: http://www.example.com/dir/other.html
- 协议是http://
- 域名是www.example.com
- 端口是80(默认端口可以省略)
那为什么需要同源策略呢?
先扔个来自MDN的概念.
同源策略 限制 从一个源加载的文档或脚本 与来自另一个源的资源 进行交互。这是一个 用于隔离 潜在恶意文件 的关键的安全机制。
比如你登录微博, 微博服务器建立了个session来记住你, 然后吧session_id返回给客户端存在cookie里, 用来辨识你. 其他网站是不能访问这个cookie的, 不然它就可以获得你得微博的cookie, 然后发送给微博服务器, 伪装成你.
跨源网络访问
但是相应的, 提升安全性的同时也限制了web应用的发展, 所以也不是所有的交互都不能进行.
比如加载cdn上的第三方JS, 图片, 嵌入iframe框等等
请参考MDN上的具体不能交互的分类:
目前来说, 需要解决的是下面3类问题
- Cookie,LocalStorage, IndexDB无法读取
- DOM无法获得
- AJAX请求不能发送
一些跨域的方式.
document.domain
页面可以更改自己的源, 脚本可以将document.domain的值 设置为 当前域 或者 当前域的超级域.
比如说(只是个例子):
http://music.baidu.com/
http://v.baidu.com/
两个地址的二级域名是相同的, 都是'baidu.com', 通过设置 document.domain = 'baidu.com'可以让两个页面共享cookie等信息, 这样当用户登录其中一个网址, 访问baidu.com域下的其他页面就不需要再次登录, 实现了SSO.
跨文档通信api
H5加入了新的API:window.postMessage()方法可以安全地实现跨源通信.
父窗口http://aaa.com向子窗口http://bbb.com:
var popup = window.open('http://bbb.com', 'title'); popup.postMessage('Hello World!', 'http://bbb.com');复制代码
反过来, 子窗口到父窗口:
window.opener.postMessage('Nice to see you', 'http://aaa.com');复制代码
通过message事件监听:
window.addEventListener('message', function(e) { console.log(e.data); },false);复制代码
postMessage方法的第一个参数是数据, 没有什么限制,
调用postMessage方法的对象就是发送消息的目标窗口, 由于窗口的地址可以改变, 第二个参数用来指定允许那些源接受消息.
协议域名端口完全匹配才能接受到消息.不然会报如下错:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://www.baidu.com') does not match the recipient window's origin ('https://www.baidu.com').
事件对象MessageEvent的属性:
- source: 发送消息的窗口
- origin: 发送消息的地址
- data: 消息内容
- message 属性表示该message 的类型
JSONP
AJAX请求只能发给同源的网址
前边有提到同源策略开放了一些限制, <script>标签相当于浏览器向src发送了一个get请求.
所以, 可以通过添加一个<script>元素,向服务器请求JSON数据,
这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
也就是通过script标签发送了一个get请求, 并通过将数据包在script中返回给客户端.
例子如下:
//客户端function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script);}window.onload = function () { addScriptTag('http://www.example.com/some?callback=callbackFunction');}function callbackFunction(data) { console.log(data);};复制代码
服务器接收到请求后,会将数据放在指定了名字的回调函数的参数位置返回.
返回到客户端的script代码如下:
callbackFunction({ a: 'a',b: 'b'});复制代码
CORS(Cross-origin resource sharing)
简单的了解过, 但是没有实际用过, 以后再总结