https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
https://juejin.cn/post/6844903972742889480#heading-10
同源策略
概念
同源策略:同端口、同域名、同协议
选择题:下列是否符合同源策略
http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端口不同)
目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
localhost 和 127.0.0.1 虽然都指向本机,但也属于跨域。
限制范围
"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
不存在跨域的情况(无视同源策略)
服务端请求服务端不存在跨域(浏览器请求服务器才存在同源策略)
< img src="跨域的图片地址"> (<img>标签的 src 属性不存在跨域)
<link href="跨域的css地址"> (<link>标签的 href 属性不存在跨域)
<script src="跨域的js地址"></script> (<script>标签的 src 属性不存在跨域)
跨域常见的方法
- JSONP
- WebSocket
- CORS
JSONP
JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
它的基本思想是,网页通过添加一个<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入<script>元素
,由它向跨源网址发出请求。
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
上面代码通过动态添加<script>
元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。
JSONP(get形式)
问:为什么jsonp只支持get请求?
JSONP 是一种【请求一段 JS 脚本,把执行这段脚本的结果当做数据】的玩法。
所以,你能 POST 一段通过 script 标签引入的脚本吗?
(如果看过 JSONP 库的源码就知道,常见的实现代码其实就是 document.createElement(‘script’) 生成一个 script 标签,然后插 body 里而已。在这里根本没有设置请求格式的余地)。
所以JSONP的实现原理就是创建一个script标签, 再把需要请求的api地址放到src里. 这个请求只能用GET方法, 不可能是POST
原理:
利用<script>
标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以
优缺点
1.优点
1.1它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略;
1.2它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
1.3在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就相
当于将controller层和view层终于分开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以
后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,
你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。
2.缺点
2.1它只支持GET请求而不支持POST等其它类型的HTTP请求
2.2它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2.3 jsonp在调用失败的时候不会返回各种HTTP状态码。
2.4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制
的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…
所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。
WebSocket
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
上面代码中,有一个字段是Origin
,表示该请求的请求源(origin),即发自哪个域名。
正是因为有了Origin
这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。
CORS
问:CORS与JSONP的比较
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
问:什么是CORS?
CORS的全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
问:如何理解CORS?
如果wang.com和ergou.com这两个网站都是我的,我就是想让wang.com去访问ergou.com里面的数据应该怎么办呢?
只需要wang.com在响应头里写ergou.com可以访问即可。这就是CORS。
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
问:CORS存在的问题
不支持IE8/9,如果要在IE8/9使用CORS跨域需要使用XDomainRequest对象来支持CORS。
简单请求
只要满足以下条件的就是简单请求:
请求方式为HEAD、POST 或者 GET
http头信息不超出以下字段:Accept、Accept-Language 、 Content-Language、 Last-Event-ID、 Content-Type(限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain)
简单请求的实现具体来说就是在信息头中加入一个Origin字段:
GET /cors HTTP/1.1
Origin: http://wang.com
Host: api.ergou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0
...
Origin
的作用就是用来说明本次请求来自哪个源,服务器会根据Origin
的值来判断是否接受本次请求。
如果Origin所表示的源不被服务器接受,即浏览器发现回应的信息头中没有Access-Control-Allow-Origin字段,就会自动抛出一个错误。
注意:这种错误是无法通过状态码识别的,这也是通过CORS实现跨域请求的一个弊端。
选择题
1. 解决跨域的方案,以下说法对的是
A、可以利用flash的http请求,来处理跨域问题
B、通过iframe设置document.domain可以实现跨域
C、一般情况下,m.toutiao.com可以ajax请求www.toutiao.com域名下的接口并获得响应
D、通过jsonp方式可以发出post请求其他域名下的接口
正确答案:B
解析:
B、站内AJAX跨域可以通过document.domain和iframe实现,document.domain;这种方式用在主域名相同子域名不同的跨域访问中
C、同源策略
D、JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域
HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2. 解决跨域的方案,以下说法对的是
A、如果接口为post请求,后端人员将接口的method改为get可以解决
B、jsonp的内部是ajax实现的
C、建议在线上使用webpack devServer proxy解决
D、建议线上接口修改Nginx增加header头解决
正确答案:C
B、jsonp请求;jsonp的原理是利用<script>标签的跨域特性,可以不受限制地从其他域中加载资源,类似的标签还有<img>.
JSONP 核心原理script 标签不受同源策略影响。动态插入到 DOM 中的 script 脚本可以立即得到执行。和ajax没有关系。
D、nginx做反向代理用的,响应头的设置是后端