zxhfighter
12/9/2013 - 6:02 AM

同源策略

同源策略

同源策略

定义


同源策略(same-origin policy)是客户端编程语言中(例如JavaScript)一个重要的安全策略。该策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。

这里的源,由协议(protocal)、主机(host)和端口(port)组成,只有三者全部相同,才为同源。

以页面http://store.company.com/dir/page.html为例,下面不同页面是否同源结果如下表。

URL 是否同源 原因
http://store.company.com/dir2/other.html 同源
http://store.company.com/dir/inner/another.html 同源
https://store.company.com/secure.html 不同源 协议不同
http://store.company.com:81/dir/etc.html 不同源 端口不同
http://news.company.com/dir/other.html 不同源 主机不同

需要注意的是,cookie相关概念中的源与这里并不相同,简单来说,cookie中的源忽略了协议和端口(?)。

例子


举个简单的例子,假如页面http://store.company.com/dir/page.html引用了cdn托管的jquery,jquery网址为http://libs.baidu.com/jquery/1.9.0/jquery.js

需要注意,jquery由页面http://store.company.com/dir/page.html加载进来,因此jquery的源为当前页面http://store.company.com:80/,而不是脚本本身的cdn来源。所以jquery可以操作当前页面。

这时,如果你用jquery的$.ajax方法去请求http://news.company.com/ajax.php的内容时,这时由于同源策略限制,你会在控制台看到如下的错误:

Unsafe JavaScript attempt to access frame with URL "http://news.company.com/dir/page.html" from frame with URL "http://store.company.com/ajax.php". Domains, protocols and ports must match.

放宽同源策略


如上面的例子,同源策略给那些使用多个子域的大站点带来了一些问题。

  1. 方案一:使用document.domain

为了支持这种类型的多域名站点,可以使用document对象的domain属性。在默认情况下,domain存放的是载入文档的服务器的主机名。可以设置这一属性,不过使用的字符串必须具有有效的域前缀或它本身。

上面例子中,可以在http://store.company.com/dir/page.htmlhttp://news.company.com/ajax.php页面中手动设置domain的值如下:

document.domain = 'comanpy.com';

这样,两个窗口就不再受同源策略的约束了,它们可以相互读取对方的属性。

  1. 方案二:跨域资源共享(CORS,Cross-Origin Resource Sharing)

例如JSONP,脚本加载等等。