同源策略和cors的信息量太多。网络上很少有全面总结的文章。学习同源策略最大的收获是,之前忽略了浏览器在安全中的重要性,总以为安全主要靠服务端。浏览器(协议规范)和服务端都非常重要。
host
https://url.spec.whatwg.org/#concept-host
domain
https://url.spec.whatwg.org/#concept-domain
根据以上的定义,domain是“域名“,比如baidu.com,host可以是domain,或者ip地址,或者opaque host。
显然对于大部分开发情况,domain等于host,就是一个域名
资料甚少,参考https://github.com/w3c/wpub/issues/321
比如file://这种host就是opaque host的一种,与常见的domain不一样。不太需要关注。
源的定义:
https://html.spec.whatwg.org/multipage/origin.html#concept-origin
基本上可以理解为
协议(http/https/...) + host(domain) + port
只能3者都一样,才叫同源。
x.baidu.com 与 y.baidu.com 就不是同源。
同源策略是互联网安全的基石。一个浏览器tab打开了源A,另一个tab打开了源B,源A的tab不能访问到源B tab的数据,包括cookie数据和dom数据。浏览器提供了这样的安全保障。
但是HTML除了cookie和dom,还有:
违反了同源策略的访问,统称为跨域访问
详细的定义可以查阅:
https://code.google.com/archive/p/browsersec/wikis/Part2.wiki
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
按照MDN的说法:
cross-origin resource sharing. 通过JS脚本来发起请求(AJAX或者fetch API, 与AJAX大同小异)
在互联网上,有的服务端愿意开放自己的数据,有的不愿意
CORS规范了不同情况下浏览器和服务端的行为。
详细说明:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
在CORS的说明中,“简单”请求不会触发CORS预检测机制。
要求“简单”请求的请求头只能有以下类型
但是浏览器发现一个请求是跨域请求时,一定会在请求中加入头部
origin
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
服务端可以根据这个头部做出相应处理。没法用脚本阻止浏览器添加此头部。
不是“简单”请求的脚本跨域请求,都是预检测请求。浏览器会执行预检测机制。
预检测机制会先用option method请求服务器,看服务端是否支持当前origin的跨域请求.
不管是简单请求还是预检测请求,涉及到的http头部常见的有:
Access-Control-Allow-Origin 允许跨域访问的域
Access-Control-Max-Age 在多长的时间内,跨域访问不再需要预检测机制
Access-Control-Allow-Headers 允许跨域时含有这些请求header
不管是简单跨域请求还是预检测跨域请求,都会发送http请求到服务端。
收到服务端返回后,如果:
即使是被服务端的返回header拒绝跨域请求,通过fiddler抓包,可以看到整个http请求是已经完成的,数据body也都传输到了浏览器。
如下图,一些请求在chrome调试器中看到请求头被标上了"provisional headers are shown", 直译就是“显示的是临时的请求头”
出现这个提示最常见的情况下数据有缓存,不过也有其他情况:
还要一种情况与跨域有关。在跨域预处理中,会先发送options请求,但是如果服务端不能正确处理options请求,会导致请求超时,出现这个警告。
通过chrome自带插件可以查看chrome的log,看看发生了什么。
chrome://net-export/
同源策略中提到一个概念叫embed cross-origin。对于这些访问,浏览器就“友好”多了。
那么像上面说的,有人在下面的src中填入一个原本会被CORS阻挡住的连接,是不是就能跳过CORS的限制?
过了浏览器还有服务端。
一般服务端默认都有如下配置:
注意:
跨域相关的返回header,比如access-control-allow-origin,对embed请求无效。这也是JSONP技术出现的原因。
如果img没有CORS的限制,是不是我可以去随意用img标签盗链别人的图片贴在我自己的网站上?
当然不。如果一个站点不想被别人盗链图片,他就会在服务端里设置:
对于script,png,gif等embed请求,统统检测请求者的referer(为什么不是检测origin?因为img不是脚本跨域请求,浏览器不会自动给这次请求加origin请求头)。
这些embed请求,浏览器都会自动加上referer请求头。
不过referer涉及到了用户的浏览记录隐私,使用下面的标签可以让浏览器不加referer请求头。
为了防止盗链,服务端的逻辑可以是:
先保证自己站点的embed请求都有referfer。服务端再检测所有请求的referer,如果没有referer或者referer不对,都拦截。
图片盗链还有另外一种思路:图片都使用随机名字,并且定期更改。
,