什么是同源?
如果两个 URL 的协议(protocol)、端口(port)、域名(host)都相同的话,则这两个 URL 是同源的。
下表给出了与 URL 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:// 默认端口是 80) |
http://news.company.com/dir/other.html |
失败 |
主机不同 |
什么是同源策略?
同源策略是web安全策略,用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。这些交互分为三类:
- 跨源写操作(Cross-origin writes)一般是被允许的。例如链接、重定向以及表单提交。特定少数的 HTTP 请求需要添加预检请求。
- 跨源资源嵌入(Cross-origin embedding)一般是被允许的。例如:
script link img video audio object embed 通过@font-face引入的字体(有些浏览器可以有 些不可以) iframe(站点可以使用 X-Frame-Options 标头来阻止)
- 跨源读操作(Cross-origin reads)一般是不被允许的
具体来讲,同源策略主要表现在DOM、Web数据、网络数据三个层面:
DOM层面。同源策略限制了来自不同源的JavaScript脚本对当前页面的DOM对象进行读写操作,从而防止跨域脚本篡改DOM结构。
Web数据层面。同源策略限制不同源的站点读取当前站点的Cookie、LocalStorage和IndexDB等数据,从而保障数据的安全性。
注意:cookie的限制不太一样,Cookie 中同源的定义,等价于不考虑 scheme 的同站(schemelessly same site)定义!Cookie 不提供根据 scheme
和 port
的隔离性。
默认情况下,Cookie 可以在 eTLD + 1
相同的站点间进行共享!
另外,服务端可以通过响应的 Set-Cookie
Header,对 Cookie 的可用性进行设定,相关的属性包括 Domain
、Path
、Secure
等。
详情参考:Cookie 的同源和同站 - Alpha Hinex's Blog
Origin 和 Site - 简书
网络层面。同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
为什么要有同源策略?
如果Web世界没有安全策略,那么我们的网站可以加载并执行别人任意的文件,这样的情况将会出现很多不可控的问题。
比如打开一个银行站点,然后又不小心打开了一个恶意站点,如果没有安全措施,恶意站点就可以做很多事情:
- 修改银行站点的DOM、CSSOM等信息;
- 在银行站点内插入恶意JavaScript脚本;
- 劫持用户登录的用户名和密码;
- 读取用户的Cookie、IndexDB等数据;
如何跨源访问?
1、CORS
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain)上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域HTTP 请求。CORS需要浏览器和服务器同时支持,整个CORS过程都是浏览器完成的,无需用户参与。因此实现CORS的关键就是服务器,只要服务器实现了CORS请求,就可以跨源通信了。
优点
- CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,容易维护;
- 支持所有类型的 HTTP 请求;
缺点
- 存在兼容性问题,特别是 IE10 以下的浏览器;
- 第一次发送非简单请求时会多一次请求。
2、JSONP
jsonp的原理就是利用script标签没有跨域限制,通过script标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。
缺点
- 具有局限性, 仅支持get方法;
- 不安全,可能会遭受XSS攻击。
3、PostMessage
解决问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
用法:
- postMessage(data,origin)方法接受两个参数
- data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
- origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
4、nginx代理
nginx代理跨域,实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段
参考:
浏览器的同源策略 - Web 安全 | MDN
浏览器同源策略 - 知乎
https://www.cnblogs.com/P1Kaj1uu/p/16815644.html