同源策略和跨域

2021-03-15  本文已影响0人  张培_

什么是跨域问题?

为什么会出现跨域问题?

因为浏览器的同源策略(同源指的是:协议+域名+端口相同)。

同源策略是浏览器的安全策略,限制某一个域的网站或者网站加载的脚本如何与另一个域的资源进行交互。

也就是浏览器为了保护当前的网站用户的信息安全,限制了当前网站与其他域的服务的交互。所谓的限制并非阻止,而是通过一些约定好的方式,决定是否进行这次跨域交互。

为什么浏览器要有同源策略

没有同源策略限制的接口请求

先补充一个context:存储在浏览器上的cookie会在浏览器向同一服务器再次发起请求时被自动携带,并发往server。

如果没有同源策略的限制,在下面这种csrf攻击的情况下,你将会受到很大的影响

没有同源策略限制的Dom查询

某一个坏的网站利用<iframe>将银行网站嵌入到自己的网站中,想要通过自己的写的js文件,拿到嵌入的银行网站的HTML username和password所在的input框的value。

如果没有浏览器的同源策略:只能access同源网站上的DOM元素, 那么坏网站上的JS就可以access银行网站上的DOM元素,这将会造成用户名和密码泄露。


由此可见浏览器的同源策略确实能在某种程度上保护了你的网站。
同源策略导致了:

但是DOM的同源策略可以理解,对于网站上的所有请求总不能因为不同源而被全部阻断,那么如何允许跨域的请求呢?

会受到同源策略影响的资源

以下是会加载外部资源的HTML标签:

会受到同源策略影响的资源

在浏览器中, <script> 、<img>、<iframe>、<link>等标签都可以跨域加载,而不受浏览器的同源策略的限制

如何解决因同源策略带来的跨域请求失败

一般我们都是采用CORS(跨域资源共享)解决此类问题的

跨域资源共享是一种基于HTTP header的机制。这个机制的原理:

Access-Control-Allow-Origin value中就是服务器能够服务的域名

Access-Control-Allow-Origin: <origin> | *

注意这里的origin是能是一个域名不能是多个

ps: 当然还包含很多其他的header,一般Access-Controll-XXX-XXX都是和跨域相关的header

当然以上只是CORS的一种场景,正常情况根据请求的不同,跨域机制也不同:

简单请求

通常请求类型是:

并且header中没有特殊的内容,只有常见的accept、content-type等

且content-type只能是application/x-www-form-urlencoded text/plain

符合上述条件的请求一般就是简单请求,简单请求的跨域机制就符合上面的步骤,只要有origin以及access-controllXX

注意如果请求的header中content-type是application/json这类请求一定不是简单请求。

非简单请求(复杂请求)

较为复杂的不在上面简单请求类型的请求就是复杂请求,浏览器在发出这类请求之前会发出一个预检请求

预检请求
是当你要发出一个跨域请求时,浏览器会自动率先发出一个OPTION类型的请求,带上Origin, 询问服务器是否能够允许接下来的实际复杂请求,预检请求会在请求头部带上实际请求的相关信息:

Access-Control-Request-Method: POST
// 实际请求的method
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
// 实际请求中即将有的header

服务器会根据预检请求带来的实际请求的信息,决定是否允许接下来的实际请求,如果允许,会在response的header中携带

Access-Control-Allow-Methods: GET, POST, PUT
// 必须字段,标明当前服务器可以允许的来自此域的所有请求method
Access-Control-Allow-Headers: X-Custom-Header
// 标明当前服务器可以允许的来自此域的所有请求能携带的header字段
Access-Control-Allow-Credentials: true
// 后续会提到
Access-Control-Max-Age: 1728000
// 可选字段,标明本次预检请求的有效时间,在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

浏览器会根据预检请求的response决定是否发送实际请求给服务器。

之后的实际请求会按照上面简单请求的流程,request会被浏览器携带origin, response必须有Access-Controll-Allow-XXX

带credentials的请求

通常HTTP请求可以通过cookie 或者 Authorization header给服务器发送身份凭证。

但是对于跨域的请求,在没有特殊设置的前提下,浏览器不会发送身份凭证信息给服务器,也就是说任何cookie或者authorization都不会自动的携带到某一个请求上。这是浏览器的同源策略之一。

那么如何将身份信息携带在请求中呢?

需要双重设置:

上一篇下一篇

猜你喜欢

热点阅读