读下来整体的感觉是很细琐,讲的很细节,我这种入门的说实话看起来有点头大。
5 深入同源策略
5.1 同源策略详解
网站的“源”由(protocol , host , port )三元组定义,同源即指这三项属性的值都相同。不过IE浏览器没有版本号这个限定条件。
区分两个概念:加载资源 , 读取资源。
加载资源不受限制,“同源策略阻止的是一个域的JavaScript代码读取另一个域的数据。比方说[[Cross-site request forgery(CSRF)跨站请求伪造]]就是不受同源策略限制的,CSRF是不能读response的。这个加载,比方说加载并显示图片,但是没办法读取图像中的像素值。
另一个问题是,如果是服务端直接发送请求,想要读取另一个源的内容。这种情况只能够读取不需要身份认证(公开?)的资源,因为它没有身份认证,从而保护了用户。
JavaScript代码的执行是当前页面URL所在的域。与代码是本身HTML中的,还是从其它页面加载的没关系。
5.2跨域DOM互访问
DOM(Document Object Model , 文件对象模型) ,浏览器对网页上各种元素的一种结构化表示形式。HTML代码解析和渲染后,以树状结构存在。
5.2.1 子域名应用互访问
同一域名的不同子域名需要交互,就可以去修改子域名页面的document.domain
属性,改成同一个父域名,就可以互相访问DOM内容。
- 修改
document.domain
,只允许修改为当前域名或父域名,否则浏览器会抛出异常 - 修改
document.domain
,会把当前源的端口置为null。这种情况下可能会受到,来自其它子域名的威胁。如果子域名修改了document.domain
,相与父域名交互,父域名也是要修改document.domain
的,因为端口号为null,不一致,所以要改。
修改document.domain
是不推荐的,更推荐通过window.postMessage
来实现跨域访问DOM。
5.2.2 通过window.name
跨域
利用了一个特性:一个窗口设置好window.name
值之后,跳转窗口,window.name
的属性值仍然保留。
但这个方法也不安全,可能泄露敏感数据。有些浏览器跳转到不同源的网站时,会把这个属性值清空,所以也不推荐用来跨域传输数据。
5.2.3 window.postMessage
方案
这个就是推荐做法,用来一个页面向另一个窗口发送消息。发送方可以指定接收方的源,接收方也能检查发送方的源。
接收方处理消息之前,要校验消息的来源,最好在此基础上再校验数据格式。
5.3 跨域访问服务端
5.3.1 JSONP方案
JSONP(JSON with Padding ),只能实现单向读操作。
跨域加载JSONP代码时,就把JSON数据作为参数传递给当前页面的源了。
- 不要再JSONP中包含敏感数据。如果不加限制,任何网站都可以载入JSONP的URL,就泄露敏感数据了。”JSONP劫持“/”只读型CSRF“。
有些蜜罐会嵌入泄露用户信息的JSONP,攻击者用自己常用浏览器访问蜜罐时,身份信息就会被泄露给蜜罐
5.3.2 跨域资源共享
Cross-Origin Resource Sharing, CORS HTML5的特性,本质上是个跨域授权策略
“简单请求”(通过普通HTML表单可以发出的请求):浏览器在请求中带上Origin
的头,表明自己的源。服务端响应时带上Access-Control-Allow-Origin
的头,用于指示哪些源可以访问自己。由浏览器判断是否能访问成功。这是由于“历史问题”造成的妥协,WebSocket就没有。
“复杂请求”:浏览器使用OPTIONS方法发送预检请求。
像是HTML表单可以提交POST请求修改服务器数据,因此CORS没法防御CSRF攻击。
http methods:
- GET
- HEAD
- POST
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
5.3.3 私有网络访问
Google在Chrome加入的私有网络访问限制,防止外部网站对内部网络(比方说路由器)发起CSRF攻击。
分成三种:
- 公共网络
- 私有网络
- 本地设备
私密性逐级递增,加载更私密的设备资源时会执行预检操作。