理解跨域资源共享(CORS)

23

我一直在网上查关于CORS的内容,想确认我的理解是否正确。

以下是一个完全虚构的场景。

以一个普通的网站为例。假设我的html页面有一个表单,包含一个文本字段名称。在提交表单后,它会将表单数据发送到myPage.php。现在,服务器在将请求与文本字段一起发送到www.mydomain.com/mydirectory/myPage.php时,会看到请求是从相同的域/端口/协议发出的。

(问题1:服务器如何知道所有这些细节?它从哪里提取所有这些细节?)

尽管如此,由于请求是由同一域发起的,它会服务于php脚本并返回所需的任何内容。

现在,为了举个例子,假设我不想手动填写文本字段中的数据,而是想通过程序实现。我创建了一个带有JavaScript的HTML页面,并随参数(即textField的值)启动了POST请求。现在,由于我的请求不属于任何域,因此服务器忽略了我的请求,并返回跨域错误?

同样,我也可以编写一个Java程序,使用HTTPClient/Post请求来完成同样的事情。

问题2:这就是问题所在吗?

现在,CORS为我们提供的是,服务器会说“任何人都可以访问myPage.php”。 从enable cors.org可以看到:

对于简单的CORS请求,服务器只需要向其响应添加以下标头即可: Access-Control-Allow-Origin: *

那么,客户端到底要如何使用这个标头呢?也就是说,客户端想要调用服务器上的资源,对吧?服务器只需要配置自己是否愿意接受请求,然后根据情况采取行动即可。

问题3:将一个标头发送回已经向服务器发出请求的客户端有什么用处?

最后,我不明白的是,比如我正在为我的 Android 应用构建一些 RESTful 服务。现在,假设我有一个 POST 服务 www.mydomain.com/rest/services/myPost。我已经让我的 Tomcat 服务器在我的本地机器上托管这些服务了。

在我的 Android 应用中,我只需调用此服务并获取结果(如果有的话)。在这种情况下我到底使用了CORS吗?它属于不同类别的服务器调用吗?如果是,那么具体是怎样的。

此外,我查看了Tomcat启用CORS,它说我可以在我的动态Web项目的web.xml中添加过滤器,然后它就会开始接受请求。

问题4:这就是使来自我的Android设备对我的Web服务调用的方法吗?

谢谢

3个回答

26
  1. 首先,跨域检查由浏览器执行,而非服务器。当JavaScript向源不同的服务器进行XmlHttpRequest请求时,如果浏览器支持CORS,则会初始化一个CORS进程。否则,该请求将导致错误(除非用户故意降低浏览器安全性)。

  2. 当服务器遇到Origin HTTP头时,服务器将决定其是否在允许的域列表中。如果不在列表中,则请求将失败(即服务器将发送错误响应)。

对于第三条和第四条,请提出单独的问题。否则,这个问题会变得太广泛。如果您不删除它,我认为它很快就会被关闭。

关于CORS的解释,请参见程序员的这个答案:https://softwareengineering.stackexchange.com/a/253043/139479

注意:CORS更多的是一种约定。它不能保证安全性。您可以编写一个恶意浏览器,忽略同源策略。它将执行从任何站点获取的JavaScript。您还可以创建任意Origin头的HTTP头,并从实现CORS的任何第三方服务器获取信息。只有在您信任您的浏览器时,CORS才能发挥作用。


1
一个支持CORS的API应该在CORS Origin不被认可时执行请求吗?我见过一种CORS的实现方式,其中请求总是被执行,但只有在Origin被认可时,服务器才设置响应中的CORS头部。不确定这是否是一个好的设计? - Josh
@Josh 我不确定。我们需要仔细查看规格。我想这需要一个全新的问题。 - sampathsris
1
@Krumia:实际上,只有在您信任浏览器的情况下才能工作的不是CORS,而是同源策略。SOP是保障机制,CORS是允许例外的便捷方式。您可以尽情信任您的浏览器,但如果您的家庭银行网站将“Access-Control-Allow-Origin”设置为“*”,那么您会遇到麻烦! - daniel f.
@sampathsris - 你所说的错误响应是什么意思?我正在使用基本的express服务器尝试cors,发送的响应是200(而浏览器会抛出错误,这表明我的有效负载仍然被传递到了一个不良域的浏览器)。 - Jonathan002

1

对于第三个问题,您需要了解两个站点和客户端浏览器之间的关系。正如Krumia在他们的回答中所提到的,这更多是请求中三个参与者之间的约定。

我最近发布了一篇文章,详细介绍了CORS握手如何设计的。


0

虽然我不是安全专家,但我希望我可以用一句话回答这个问题。

如果启用了CORS,则服务器将仅询问浏览器是否从[xzy.com]调用请求?如果浏览器说是,它将显示结果;如果浏览器说不是,而是从[abc.com]调用的,则会抛出错误。

因此,CORS取决于浏览器。这就是为什么浏览器在实际请求之前发送预检请求的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接