首页
Preview

详解跨源资源共享(CORS)及其在Web开发中的应用

什么是 CORS(跨源资源共享)?

CORS(跨源资源共享)是一种基于HTTP并由Web浏览器控制的安全机制。它允许客户端请求来自自身以外源(跨源)的资源。这是为了应对同源策略(SOP{Same Origin Policy})而设计的。所有常见的Web浏览器都实现了它,并于2014年1月被W3C推荐为标准。简单来说,可以将其看作是一种应对跨源资源的技术。

那么它是如何应对同源策略的呢?

为了理解CORS,我们需要先了解同源策略的必要性。

同源策略(SOP)

同源策略将具有相同组合的方案(协议)、主机和端口视为同源,并把它们作为同样受保护的资源来处理。例如,如果我们有一个URL,比如https://example.com/explain_cors,那么源就是以下部分:

同源策略是一种安全限制,用于阻止一个网站的JavaScript等客户端脚本访问另一个网站的资源。如果iframe中嵌入的页面可以使用JavaScript进行访问,那么登录信息等敏感信息可能就会被获取。如果嵌入的是自己的网站,那么没有问题,但如果被外部站点随意嵌入并通过JavaScript窃取信息,那就会产生安全问题。为了保证这种安全性,浏览器采用了同源策略。实际上,我们可以通过一些实验来验证浏览器的同源策略是否有效。

例如,从网址:http://localhost:3000 向同一源的http://localhost:3000/api 发送请求。

image.png

请求被正常处理。然后,让我们试着向一个不同源的http://site.localhost:3000/api 发送请求。

image.png

请求被CORS策略阻止。这证明了同源策略是起作用的。

然而,也有一些场景我们可能需要使用跨源资源。比如,需要为A站点提供一个生成唯一ID的API。

站点A:https://example.com

提供ID的API:https://api.example.com

在这种情况下,站点A会执行一段js代码,这段代码会向提供ID的API发送请求。API生成数据后返回给站点A。然而,由于这两个站点的源不同,同源策略就不允许这种请求,这就需要CORS来解决。

CORS 的工作原理

CORS 请求大致分为两种类型。

  • 简单请求(Simple Request)
  • 预检请求(Prefilight Request)

这两种请求的行为是不同的,为什么会有这么大的区别呢?首先,是浏览器自动决定应该使用哪种类型的请求。浏览器是根据以下原则决定的:如果请求没有符合一些特定的条件,那么就将其作为预检请求处理。

简单的请求

浏览器在以下条件下判定该请求为简单请求: 基本上,这适用于包含令牌等敏感信息的可能性较低的情况。

  • HTTP 方法是GET、HEAD或POST

  • 包含的头信息仅为以下几种:

       - Accept
       - Accept-Language
       - Content-Language
       - Content-Type (但只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
    

简单请求的CORS处理方式

即使没有CORS支持,从浏览器到服务器的请求也会正常发送。服务器端的请求处理也是正常的,但由于跨域,浏览器并不返回响应,而是报错。解决这个问题的方法就是在服务器端设置允许来自哪个域的访问。通过设置Access-Control-Allow-Origin就可以解决这个问题。

如果从站点A:https://example.com 向提供ID的API:https://api.example.com 发送请求,那么服务器端(API)就需要进行如下设置:Access-Control-Allow-Origin: https://api.example.com这样一来,如果域名匹配,就被认为是正常的响应,浏览器就不会报CORS错误了。

预检请求

如前文所述,如果请求不符合简单请求的特定条件(也就是说,浏览器认为请求存在风险),就会被视为预检请求。在预检请求中,当浏览器向服务器发送请求时,首先要发送一个HTTP Option请求。这个Option请求就是预检请求的特征。在实际的请求之前,浏览器首先发送一个Option请求以获取CORS设置。然后,浏览器根据预检请求的结果来决定是否进行实际的请求。因此,与简单请求不同,预检请求不必担心会执行服务器端的操作。这就是简单请求和预检请求的主要区别。

预检请求的CORS处理方式

要处理预检请求,服务器端需要对Option方法的请求进行响应。


app.options('*', (req, res) => {
  res.set('Access-Control-Allow-Origin', '<https://example.com>');
  res.set('Access-Control-Allow-Methods', 'GET, POST');
  res.set('Access-Control-Allow-Headers', 'Content-Type');
  res.status(204).end();
});

这样,对于请求,服务器可以返回Option方法的响应,并添加CORS设置。

  • Access-Control-Allow-Origin 用于指定允许的域名。
  • Access-Control-Allow-Methods 用于指定允许的 HTTP 方法(GET,POST)。
  • Access-Control-Allow-Headers 用于指定请求中可以包含的头部类型。

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
老朽.
做好人没希望,做坏人不擅长。

评论(0)

添加评论