[TOC]
1、概述
同源策略是对JavaScript
代码能够操作哪些WEB
内容的一条完整的安全限制,也是由Netscape
提出的一个著名的安全策略。所谓同源简单来说就是“三个相同”,
**
1、域名相同
2、协议相同
3、端口相同
**
当我们使用多个<iframe>
元素或者打开其他浏览器窗口的时候,这一策略就会发挥它的作用,在这种情况下,同源策略负责管理窗口或者窗体中的JavaScript
代码以及和其他窗口的交互,具体来说,脚本只能读取所属文档的来源相同的窗口和文档属性(当然我们也可以通过JS实现多个窗口和窗体,在本章我们不做解释)当然同源策略也属于一些理论性的知识点,存在于我们日常的使用中,了解这些能够帮助我们更好的理解前端的安全及知识。
文档的来源包含协议、主机,以及载入文档的URL
端口。
1、从不同的web
服务器载入的文档具有不同的来源。
2、通过同一主机的不同端口载入的文档具有不同的来源。
3、使用http
协议和https
协议载入的文档具有不同的来源。
即使他们来自同一个服务器。
脚本本身的来源与同源策略并不相关,相关的是脚本所潜入的文档的来源,同时同源策略还会应用于XMLHttpRequest
生成的HTTP请求,这个对象允许客户端javascript
生成任意的HTTP
请求到脚本所属文档的服务器,但是不允许脚本和其他WEB服务器之间的通信,这就是我们常说的跨域请求,其实所谓的跨域就是受到了同源策略的约束,(当然我们可以通过其他的方式来解决跨域之间的请求的问题)。
2、同源策略的目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,”同源政策”是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
—— 摘自《浏览器同源政策及其规避方法》
3、文档中设置同源:document.domain
在某些情况下,同源策略就显得比较严格了,比如在同一个域名下的其它子域名,例如两个子域名:home.xiang.com
和子域名order.xiang.com
其中的一个子域名下需要合法的读取另一个子域名地下的文档的属性,为了支持这种多域名站点,这时候我们可以使用document.dimin
属性来控制源,在默认情况下document.domain
的值是载入文档的服务器的主机名,当我们在设置这一属性的时候,我们使用的字符串必须具有有效的域前缀或它本身。
因此如果一个dimin初始值是home.xiang.com
的字符串我们可以设置为xiang.com
。另外document.domain
的值中必须又一个点号,不能把它设置为com
或者其它顶级域名。
这时,如果两个窗体或者窗口包含的脚本吧document.domain
设置成了相同的值,那么两个窗口就不再受同源策略的约束了。可以相互读取属性了。
4、请求中的 Access-Control-Allow-Origin
受到同源策略的影响,同时我们也可以通过一些方法来达到跨域资源的共享,参见http://www.w3.org/TR/cors/ 这个标准和草案是用新的Origin:
请求头和新的Access-Control-Allow-Origin
相应来扩展HTTP,它允许服务器用头信息显示的列出源,或使用通配符来匹配所有的源并允许由任何地址请求的文件,很多浏览器都使用这种新的头信息来允许跨域的HTTP请求,这样在我们的XMLHttpRequest
就不会被同源策略限制。
5、跨文档消息传递 window.postMessage()
跨文档消息,允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不管脚本的来源是否相同,当我们调用window对象上的postMessage方法时就可以异步的将信息传递到指定的窗口文档,此时被接受的窗口中可以通过onmessage()
的方法来接收到传递过来的信息,但是不能调用其他文档的方法或者读取属性。也就是说这只是一种通信技术,并非是去控制另一个文档的内容。
postMessage()
方法接受两个参数,第一个参数是要传递的信息,HTML5标准中提到,该参数可以是任意基本类型的只或者是可以复制的对象,但是有些浏览器只支持字符串的传递,所有有时候传递的对象或者数组的时候需要进行转换。第二个参数是一个字符串,是指定窗口的源,也就是指定窗口的document.domain
属性的值,这其中包括了协议、主机名、以及URL端口部分,(除了这些信息之外的信息都会被忽略),如果需要传递给任何窗口,此时这个只可以设置为*
,如果要指定和当前窗口同源的话也可以使用/
即可。
在目标窗口就会触发onmessage()
事件,该事件接收到的是一个对象,包含一下属性:
data
作为第一个参数传递给
postMessage()
方法的消息副本内容。
source
消息源自的window对象。
origin
一个字符串,指定消息来源(URL)。
——摘录
本文大部分内容摘自《JavaScript权威指南》一书,详细解说请参考书中内容。