引入飞行前要求的动机是什么?
引入了预检请求,以便浏览器在发送某些请求之前可以确定它正在处理支持CORS的服务器。这些请求被定义为既具有潜在危险(状态更改)又是新的请求(由于“ 同源起源策略”,在CORS之前是不可能的)。使用预检请求意味着服务器必须(通过正确响应预检)选择接受CORS可能导致的新的,潜在危险的请求类型。
这就是规范这一部分的含义:“为了保护资源免受在该规范存在之前可能源自某些用户代理的跨域请求,将进行预检请求以确保资源了解此规范。”
能给我举个例子?
假设有一个浏览器用户登录到其银行网站,网址为A.com
。当他们导航到恶意程序时B.com
,该页面会包含一些Javascript试图将DELETE
请求发送到A.com/account
。由于用户已登录A.com
,因此该请求(如果发送)将包含标识该用户的cookie。
在CORS之前,浏览器的“相同来源策略”将阻止其发送此请求。但是,由于CORS的目的是使这种跨域通信成为可能,所以这不再合适。
该浏览器可以简单地发送DELETE
,让服务器决定如何处理它。但是,如果A.com
不知道CORS协议怎么办?它可能会继续执行并执行危险DELETE
。可能已经假定,由于浏览器的“同源策略”的影响,它永远不会收到这样的请求,因此可能从未针对这种攻击进行过加固。
然后,为了保护此类不支持CORS的服务器,该协议要求浏览器首先发送预检请求。这种新的请求是只有支持CORS的服务器才能正确响应的请求,使浏览器可以知道发送实际请求是否安全DELETE
。
为什么对浏览器如此大惊小怪,攻击者不能DELETE
仅从自己的计算机发送请求?
可以,但是这样的请求将不包含用户的cookie。旨在防止这种攻击的方法是,浏览器将与请求一起发送其他域的cookie(特别是用户的身份验证信息)。
这听起来像跨站请求伪造,其中在网站上的表单B.com
可以POST
给A.com
用户的cookies和进行破坏。
那就对了。进行这种处理的另一种方式是创建预检请求,以免增加非可识别CORS的服务器的CSRF攻击面。
但看的要求,对于不要求preflights“简单”的要求,我看POST
还是允许的。这样就可以更改状态并删除数据DELETE
!
确实如此!CORS不能保护您的站点免受CSRF攻击。再有,如果没有CORS,您也不会免受CSRF攻击。飞行前请求的目的仅仅是将CSRF的暴露范围限制在CORS之前的世界中。
叹。好的,我很勉强接受飞行前要求。但是,为什么我们必须对服务器上的每个资源(URL)都这样做呢?服务器要么处理CORS,要么不处理。
你确定吗?多台服务器处理单个域的请求并不少见。例如,可能是A.com/url1
由一种服务器处理请求而由另一种服务器处理请求的情况A.com/url2
。通常,处理单个资源的服务器不能对该域上的所有资源进行安全保证。
精细。让我们妥协吧。让我们创建一个新的CORS标头,该标头允许服务器确切说明它可以使用的资源,从而可以避免对这些URL进行其他预检请求。
好主意!实际上,Access-Control-Policy-Path
仅出于此目的而提出了标题。最终,尽管如此,它最终还是被排除在规范之外,这显然是因为某些服务器错误地实现了URI规范,从而导致对浏览器似乎安全的路径请求实际上在损坏的服务器上并不安全。
这是一个明智的决定,即优先考虑安全性而不是性能,以允许浏览器立即实施CORS规范而不会给现有服务器带来风险吗?还是为了将Internet浪费在带宽上而使延迟加倍,只是为了适应特定时间在特定服务器中的错误,是否是短视?
意见不同。
好吧,至少浏览器会为单个URL缓存预检吗?
是。虽然可能不会持续很长时间。在WebKit浏览器中,最大的预检缓存时间目前为10分钟。
叹。好吧,如果我知道我的服务器支持CORS,因此不需要预检请求提供的保护,那么有什么办法可以避免它们?
你唯一真正的选择是,以确保您符合要求的“简单”的请求。这可能意味着遗漏了您可能会包含的自定义标头(如X-Requested-With
),位于Content-Type
或附近。
无论做什么,都必须确保已设置适当的CSRF保护,因为CORS规范未解决拒绝“简单”请求(包括不安全请求)的问题POST
。正如规范所指出的那样:“对于简单请求具有重要意义而不是检索的资源,必须保护自己免受跨站点请求伪造的侵害”。