您真的认识CORS吗?

跨域资源共享

所请求的资源上没有“ Access-Control-Allow-Origin”标头。 因此,不允许访问 原始站点 http://www.sesamestreet.com

如果您有时使用前端,则很可能您之前已经看到过上述错误。 当您第一次遇到这种情况时,就像其他适当的开发人员所做的那样,您会用Google搜索。 结果,您可能已经在StackOverflow上看到了一些建议,在服务器的响应中包含Access-Control-Allow-Origin ,然后您可以再次返回满意的编码。

令人惊讶的是,对于许多开发人员而言,这就是跨域资源共享(CORS)体验的结尾。 他们知道如何解决问题,但是他们并不总是理解为什么问题首先存在。 在这篇简短的文章中,我们将更深入地探讨这个主题,试图了解CORS真正解决了什么问题。 但是,我们将从同域策略(SOP)概念开始。

什么是原产地政策?

SOP是几乎在所有现代浏览器中实现的安全机制。 它不允许从一个来源加载的文档或脚本访问其他来源的资源。 要了解为什么它如此重要,重要的是要认识到,对于到特定域的任何HTTP请求,浏览器都会自动附加绑定到该域的所有cookie。 假设为域CookieMonster.com存储了一个cookie my_cookie=oreo oreo。

CookieMonster.com是一个单页应用程序,它使用在CookieMonster.com/api中公开的REST API。 因此,对于对该API的每个HTTP调用, my_cookie=oreo将附加到该请求。

如果没有“同源策略”,则可能出现以下情况:

SesameStreet.com可以重复使用先前存储在CookieMonster.com上的用户cookie。 听起来吓人吗? 还没? 让我们看一下更发人深省的场景:

然后:

如果没有SOP,MaliciousWebsite.com将能够使用为MyBank.com存储的会话cookie将请求发送到MyBank.com/api。 这是为什么? 因为,如前所述,浏览器会自动附加绑定到目标域的cookie。 无论请求是来自MyBank.com还是MaliciousWebsite.com都没有关系-只要请求发送到MyBank.com,就会使用为MyBank.com存储的cookie。 如您所见,如果没有“同源策略”,则跨站请求伪造(CSRF)攻击可能相对简单–假设身份验证仅基于会话cookie(而不是基于令牌的身份验证)。 这就是引入SOP的原因之一。

话虽如此,浏览器始终可以通过在<img><script><iframe>标记中指定来自外部域的资源来进行跨域请求,并且可能会附加cookie。 关键的区别是AJAX调用是从JavaScript代码中触发的,它具有完全的控制权,并且可能具有潜在的危险。 另一方面,标签由浏览器控制,并且没有JS代码可以拦截它们触发的HTTP请求。

什么是起源?

在上一段中,我以域为例。 但是,“同源政策”适用于……嗯,起源。 如何定义原点? 如果两个源具有相同的协议,主机和端口(有时称为“方案/主机/端口元组”),则认为它们是相等的。 它解释了为什么即使后端和前端都在本地运行,我们也看到此错误的原因-它们使用不同的端口,因此它们的来源也不同。

什么是CORS?

即使有人将CORS称为安全机制,但事实恰恰相反。 这是放松安全性,减少限制的一种方法。 SOP几乎在所有现代浏览器中实现,因此,不允许一个来源的网站访问国外来源的资源。 CORS是一种使之成为可能的机制。

CORS如何运作?

CORS定义了两种类型的请求:简单请求和预检请求。

简单的要求

简而言之,一个简单的请求就是不会触发飞行前请求的请求。 满足以下所有条件的请求不会触发预检请求:

  • 使用GET,HEAD或POST方法
  • 规范中定义的小子集外,没有其他标头(任何自定义或授权标头都打破了此条件)
  • Content-Type标头的唯一允许值是application/x-www-form-urlencodedmultipart/form-datatext/plainapplication/json打破了此条件)

典型的场景是:

1.在浏览器选项卡中打开SesameStreet.com。 它启动AJAX请求(使用XMLHttpRequest或Fetch API)以获取CookieMonster.com/api/monsters

2.浏览器注意到这是一个跨域请求,并附加了Origin请求头:

GET api/monsters HTTP/1.1
Host: cookiemonster.com
Origin: https://www.sesamestreet.com
...

3.配置了CORS的服务器检查Origin标头,如果允许原点,则将Access-Control-Allow-Origin标头设置为Origin值:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.sesamestreet.com
...

4.当响应到达浏览器时,浏览器将验证Access-Control-Allow-Origin标头下的值是否与请求所源自的选项卡的Access-Control-Allow-Origin相匹配。

事前要求

如前所述,即使添加标头(例如Authorization),也会导致请求被预检。 如果浏览器首先发送附加的初步OPTIONS请求(“预检请求”)以确定实际请求(“预检请求”)是否安全,则该请求将被预检。 让我们看一下我们要创建新怪物资源的典型流程:

1.使用SesameStreet.com的浏览器选项卡使用POST方法使用JSON负载向CookieMonster.com/api/monsters发出AJAX POST请求。 浏览器知道发送带有Content-Type的POST不同于application/x-www-form-urlencodedmultipart/form-datatext/plain ,因此它发送带有三个附加参数的OPTIONS请求:

  • 起源–我们已经知道的那个
  • Access-Control-Request-Method –主(预检)请求的HTTP方法
  • Access-Control-Request-Headers –主(预检)请求的HTTP标头
OPTIONS /api/monsters HTTP/1.1
Host: cookiemonster.com
Origin: https://www.sesamestreet.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
...

2.服务器以允许的来源,方法和标头进行响应。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.sesamestreet.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type

3.如果允许源,并且服务器返回的列表中包含主请求的HTTP方法和标头,则可以发送主请求。 这将是一个常规的跨域请求,因此它将包含Origin头,并且响应将再次包含Access-Control-Allow-Origin

性能说明–每次发送预检请求可能会带来性能开销。 这可以通过使用Access-Control-Max-Age响应头缓存预检请求来缓解。

关于CORS的常见误解

乍一看,服务器端的CORS配置看起来像某种ACL(访问控制列表)-服务器返回其接受请求的来源。 访问资源的唯一方法是从服务器列入白名单的来源发送请求,对吗? 并不是的。 请记住,HTTP不仅被浏览器使用,而且您可以从任何客户端(例如curl,Postman等)发送HTTP请求。 如果您在这些工具中准备了自定义HTTP请求,则可以放置所需的任何Origin标头。 您也可以跳过它,并且服务器通常无论如何都会返回正确的结果。 这是为什么? 因为如前所述,“同源策略”是在浏览器中实现的概念。 其他工具或软件组件对此不太在意。

根据您刚刚阅读的内容,有一个简单的含义。 如果有您要使用网页的第三方API,但是该API返回Access-Control-Allow-Origin标头设置为您自己的来源以外的其他来源,那么您可以通过设置代理服务器来解决此问题。 为什么? 因为如上所述,SOP不适用于服务器到服务器的通信,而仅适用于浏览器到服务器的通信。

CORS安全吗?

最重要的问题–从本文开始的CSRF方案是否可以使用CORS? 答案是,这取决于。 默认情况下, CORS不在跨域请求中包含cookie 。 这与旧的跨域技术(例如JSON-P(带填充的JSON))不同。 此行为大大减少了CSRF漏洞。 但是,如果您确实希望在请求中发送cookie,则可以明确允许。 这需要客户端和服务器端之间的协调。 您的网站必须将XMLHttpRequest的withCredentials属性设置为true (或将Fetch API中的credentials属性设置为include )。 此外,服务器必须以Access-Control-Allow-Credentials标头设置为true响应。 通过这种组合,双方都同意在发送跨域请求时使用凭据。 凭据是cookie,授权标头或TLS客户端证书。 值得庆幸的是,有一种安全措施可以防止过度的暴露狂–以下组合无效:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *

如果您允许发送凭据,则不能将Access-Control-Allow-Origin设置为通配符。 服务器必须返回允许访问资源的显式来源。 坏消息是许多服务器根据用户请求中的Origin值盲目生成Access-Control-Allow-Origin标头。 如果真是这样,将Access-Control-Allow-Credentials设置为true可能会造成严重的安全漏洞。

翻译自: https://www.javacodegeeks.com/2018/09/really-know-cors.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值