浏览器同源策略详解

介绍

浏览器的同源策略是指对请求地址与请求源不一致的请求回来的响应做出一定限制的策略,即如果服务端对于跨源请求的响应中如果不符合浏览器的同源策略规范,那么浏览器将不会展示响应内容。

两个URL的协议主机端口号只要有一个不同,那么就视为不同源。

这里涉及到一个很重要的点,即我们发送出去的跨源请求并非没有到达服务器,只是浏览器会根据服务端返回的响应头的相关字段决定是否展示响应内容

CORS相关的字段可以参照这篇文章跨域资源共享 CORS 详解,里面详细介绍了CORS的相关字段是怎么影响CORS请求在浏览器中是否成功的。

值得注意的是,对于GETPOSTHEAD方法,即使响应头中的Access-Control-Allow-Methods不包括他们,只要Access-Control-Allow-Origin字段对上了请求时的Origin,那么也算预检请求成功。可以看作GETPOSTHEAD这三个值是Access-Control-Allow-Methods的默认值,再设置Access-Control-Allow-Methods字段只是往里面添加更多允许的方法。

浏览器将这样的跨源请求(CORS)分为两大类:简单请求复杂请求

简单请求

简单请求的定义可以参照MDN文档,不符合里面规定的则视为复杂请求。

区别

二者的区别就在于复杂请求再发送前不会发送预检请求(preflight)。预检请求的目的在于虽然浏览器对于一些CORS不会让其成功,但其有确确实实地请求到了服务器上,这就可能造成如果没有预检请求的话,那么一个删除的CORS请求到了服务器,并且成功造成了影响,但是浏览器却由于同源策略不会返回响应的结果。所以一般浏览器在发送实际的CORS之前,会先发送预检请求,询问服务器是否允许跨源,如果不允许就不会发送实际的请求了,避免对服务器的数据造成影响。

需要注意的是,在最近的Chrome版本中,即使是一个简单请求,如果它访问的地址是一个专用网络,那么也会先发起一个预检请求,参照专用网络的访问:引入预检请求

文档里详细说明了什么时候算访问一个专用网络,比如在公网中访问局域网,或者在局域网中访问本地网络(localhost) 。

至于为什么访问专用网络也需要发送预检请求,是因为在这种情况下,可能会发生DNS重绑攻击。这篇文章很好介绍了DNS重绑攻击的原理:详解DNS重绑定攻击

但其实细想会发现预检请求貌似很没有必要。因为服务器端完全可以根据CORS请求的请求源判断是否要响应该请求,如果不符合要求直接拒绝就行了,犯不着浏览器先发一次预检请求。事实确实是这样的。对于已经对CORS有防范的服务器来说,预检请求确实是多余的,但浏览器的同源策略是后来才出现的,在此之前的服务器并没有对CORS进行防范,他们并不会刻意区分请求的源,而是会对他们都进行响应,那么确实会造成上面说的情况,所以浏览器才加以种种限制,以保护这类服务器。这也是为什么说浏览器的同源策略是一个君子协议,其只在浏览器端生效。

可以看看这个帖子:为什么要引入预检请求?

HTML标签中的跨域

很多HTML标签都能发送请求,比如form表单,a标签,img标签等等,但有一些是不会加以限制的,譬如JSONP,就是利用了script标签不受跨源策略的影响。

实质

我觉得这个问题下的答案说得非常好:为什么form表单提交没有跨域问题,但ajax提交有跨域问题?

一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容。但浏览器并不阻止你向另一个域名发送请求。

猜你喜欢

转载自blog.csdn.net/weixin_55658418/article/details/129464685
今日推荐