Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥【前后端】跨源资源共享了解下 #87

Open
reng99 opened this issue Mar 18, 2021 · 0 comments
Open

🔥【前后端】跨源资源共享了解下 #87

reng99 opened this issue Mar 18, 2021 · 0 comments
Labels
blog a single blog

Comments

@reng99
Copy link
Owner

reng99 commented Mar 18, 2021

Access to fetched has been blocked by CORS policy在控制台的报错信息相信你遇到过。

这就是CORS造成的。

比如:

我们的网站www.mywebsite.com想通过位于www.anotherdomain.com的服务器那里获取用户数据~

foreward.gif

CORS为什么会产生呢?又意味着什么?

同源策略

同源策略的目的,是为了保护用户的信息安全,防止恶意的网站窃取数据

without-same-origin-policy.gif

with-same-origin-policy.gif

同源策略是指在WEB浏览器中,允许某个网页脚本访问另外一个网页的的数据,但是这两个网页必须有相同的URI、主机名和端口号,一旦两个网站满足上述的条件,这两个网站就被认定为具有相同的源

如图:

same-origin-policy.png

客户端CORS

javascript脚本请求中,我们只能获取同源的资源。

same_origin.gif

嗯...我们经常需要获取跨源的资源,获取后端的数据呢?为了保证跨源请求安全,浏览器使用了CORS机制。

CORS全称Cross-Origin Resource Sharing,即跨源资源共享。虽然浏览器不默认允许我们跨源请求资源,但是,我们可以使用CORS来更改这个安全限制,来保证我们获取的跨源资源依旧是安全的。

当跨源请求发起,客户端会自动在HTTP请求头中添加OriginOrigin的值就是表明资源从哪里来。

origin_come_from.gif

为了保证客户端能够获取跨源资源,这还需要服务端在响应头上做出特定的回应。

服务端CORS

作为一个服务端开发者,我们应该允许必要跨源的请求,在响应中设置额外的响应头Access-Control-*来完成。

虽然有几个响应头我们可以设置--可参考,但是客户端知道一个即可:Access-Control-Allow-Origin

Access-Control-Allow-Origin指定哪个源上的资源被允许。

比如服务端允许源https://mywebsite.com访问它的资源。

Access-Control-Allow-Origin.gif

漂亮!我们可以收到服务端返回的数据了~

access_control_allow_origin_success.gif

在上图的例子中,客户端CORS机制,它会检查响应头上的Access-Control-Allow-Origin值是否包含它发起请求头的Origin值。我们请求头的originhttps://www.mywebsite.com,在响应头的Access-Control-Allow-Origin列表中。

judge_same_origin.gif

那么,如果请求头origin上的值,不在响应头的Access-Control-Allow-Origin的列表中,就会发生下面的错误~

error_same_origin.gif

错误很明显了:

The 'Access-Control-Allow-Origin' header has a value
 'https://www.mywebsite.com' that is not equal 
to the supplied origin. 

通配符 * 表示任何的源都可以访问本服务端。所以请慎用~

Access-Control-Allow-OriginCORS中一个比较常用的响应头参数,表明哪些请求的来源可以被通过或者被禁止。

Access-Control-Allow-MethodsCORS中另一个比较常用的响应头参数,表明跨源的哪些请求方法被限制在响应头此参数列表中。

access_control_allow_method.gif

在上图的示例中,GET, POST 或者 PUT 被允许通过,而 PATCH 或则 DELETE 则会被阻塞~

说到 PUT, PATCHDELETE 方法,CORS对它们的处理又有些不同,它们会执行预检请求

预检请求

CORS有两种类型的请求:简单请求预检请求。区分两种请求取决于其请求的数据--

简单总结:GET,HEADPOST这些方法,并且他们没有自定义的header参数,那就是简单请求了;而PUT,PATCHDELETE这些方法就是预检请求了。

对于简单请求和预检请求的详细解释,可以参考MDN这里

那么,预检请求意味着什么?

在真正的请求发送之前,客户端生成一个预检请求。预检请求会在请求头Access-Control-Request-*包含真正请求的信息,然后给到服务端。

preflighted.gif

服务端收到了预检请求后,然后返回一个空的返回体但是带上CORS响应头。浏览器收到响应,然后检查请求是否被允许了✔。

preflight_response.gif

在预检请求通过之后,浏览器就会发起真正的请求,服务端这个时候才返回我们想要的数据。

preflight_pass.gif

如果预检请求没通过,真正的请求就不会被发起。

💡为了减少请求往返的次数,我们可以在发送CORS的请求头中,添加Access-Control-Max-Age,来缓存预检响应。这样我们就可以使用缓存的预检响应,而不是再次发起一个请求。

凭证

Cookiesauthorization headersTLS certificates默认只能在同源请求生效。

但是我们可以通过在CORS中请求头中添加Access-Control-Allow-Credentials来更改这种默认请求,而达到获取凭证的目的。

如果我们想在cross-origin的请求中包含cookies和其他的验证头,我们需要将请求中字段withCredentials设置为true,在响应头中添加Access-Control-Allow-Credentials,如下:

credential.gif

至此,本文完结❀

如果你想了解CORS更多详细的内容,不妨找个时间读读the W3 spec

最近文章列表:

码字不易,走过路过赞一个否?

ε=ε=ε=┏(゜ロ゜;)┛

@reng99 reng99 added the blog a single blog label Mar 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog a single blog
Projects
None yet
Development

No branches or pull requests

1 participant