本文首发于知乎 《浏览器同源策略以及Script Error错误》 ,搬运转载请注明出处,否则追究版权责任。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
一个源的定义
如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
下表给出了相对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 |
失败 | 不同协议 ( https和http ) |
http://store.company.com:81/dir/etc.html |
失败 | 不同端口 ( 81和80) |
http://news.company.com/dir/other.html |
失败 | 不同域名 ( news和store )<br /> |
源的继承
data:URLs获得一个新的,空的安全上下文。
在页面中用 about:blank
或 javascript:
URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URLs 没有明确包含有关原始服务器的信息。
例如,about:blank
通常作为父脚本写入内容的新的空白弹出窗口的 URL(例如,通过 Window.open() 机制)。 如果此弹出窗口也包含代码,则该代码将继承与创建它的脚本相同的源。data:
URL会得到一个新的空的安全上下文。
script标签的crossorigin属性
crossorigin的属性值可以是anonymous
、use-credentials
,如果没有属性值或者非法属性值,会被浏览器默认做anonymous
。crossorigin的作用有三个:
-
crossorigin会让浏览器启用CORS访问检查,检查http相应头的Access-Control-Allow-Origin
-
对于传统script需要跨域获取的js资源,控制暴露出其报错的详细信息
-
对于
module script
,控制用于跨域请求的凭据模式
我们在收集错误日志的时候,通常会在window上注册一个方法来监测所有代码抛出的异常:
window.addEventListener('error', function(msg, url, lineno, colno, error) { var string = msg.toLowerCase() var substring = "script error" if (string.indexOf(substring) > -1){ alert('Script Error: See Browser Console for Detail') } else { var message = { Message: msg, URL: url, Line: lineNo, Column: columnNo, 'Error object': JSON.stringify(error) } // send error log to server record(message) } return false })
但是对于跨域js来说,只会给出很少的报错信息:'error: script error',通过使用crossorigin
属性可以使跨域js暴露出跟同域js同样的报错信息。但是,资源服务器必须返回一个 Access-Control-Allow-Origin
的header,否则资源无法访问。
为什么错误信息要遵守同源策略?
如果你在访问一个恶意网站,页面上有一段<script src="yourbank.com/index.html">
,当发生了脚本错误,错误信息可能会透露出你是否已经登录了(如果你已经登录了,错误信息可能是 “欢迎 Fred...” is undefined,如果你没登录,错误信息可能是“请登录...” is undefined 之类的)。如果这个恶意网站对很多银行机构进行了该行为,他们很容易就知道你是在访问哪家银行,就能做出更具有针对性的钓鱼页面。