了解页面响应

Posted

技术标签:

【中文标题】了解页面响应【英文标题】:Understanding Page Response 【发布时间】:2018-01-24 19:15:32 【问题描述】:

我正在尝试了解整个 CORS 政策的运作方式。为了解释我的困惑,让我举个例子:

$.get("https://www.google.com", function(response)  alert(response) );

上述请求将返回以下错误:

XMLHttpRequest 无法加载 https://www.google.com/。从“https://www.google.com/”重定向到“https://www.google.ca/?gfe_rd=cr&ei=TlqUWeGEH5HRXqW6utgI”已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'https://fiddle.jshell.net' 因此不允许访问。

现在,为了让它发挥作用,谷歌必须将 https://fiddle.jshell.net 列入白名单。

现在,如果我要在一个安静的 API 页面上尝试同样的事情,那将是可行的。我的问题很简单,为什么?

为了分析这一点,我尝试点击一个 API 并分析它的响应:

https://apigee.com/console/bing?req=%7B%22resource%22%3A%22web_search%22%2C%22params%22%3A%7B%22query%22%3A%7B%22query%22%3A%22sushi%22%2C%22sources%22%3A%22web%22%7D%2C%22template%22%3A%7B%22format%22%3A%22json%22%7D%2C%22headers%22%3A%7B%7D%2C%22body%22%3A%7B%22attachmentFormat%22%3A%22mime%22%2C%22attachmentContentDisposition%22%3A%22form-data%22%7D%7D%2C%22verb%22%3A%22get%22%7D

回复:

HTTP/1.1 200
Date:
Wed, 16 Aug 2017 14:31:32 GMT
Content-Length: 266
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Server: Apigee Router
X-Content-Type-Options: nosniff

我得出结论,它一定是标题。具体来说,我相信它是这个标题:Content-Type: application/json; 但我不确定,我正在努力理解这一点,希望这里有人可以向我解释。

【问题讨论】:

我不知道“在一个安静的 API 页面上尝试同样的事情”是什么意思,但它的要点是,默认情况下,浏览器会阻止您的前端 javascript 代码访问来自跨平台的响应。 origin 使用 XHR 或来自 Javascript 库的 Fetch API 或 Ajax 方法请求您发送 - 除非正在发送请求的服务器表明它选择接收此类请求。服务器表明选择加入的方式是在其响应中发送 Access-Control-Allow-Origin 响应标头。 如果您想了解 CORS 协议的工作原理,developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 是最好的起点 【参考方案1】:

所以我做了 2 个测试:从控制台运行您的代码 $.get("https://www.google.com", function(response) alert(response) ); sn-p 并从 https://apigee.com/console/others 请求 https://www.google.com

我认为在第一种情况下发生的情况是请求是从客户端完成的,下一个请求标头被发送:

:authority:www.google.com
:method:GET
:path:/?_=1502896196820
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.8
origin:https://***.com
referer:https://***.com/questions/45717044/understanding-page-response
user-agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/62.0.3187.0 Safari/537.36
x-chrome-uma-enabled:1
x-client-data:CJG2yQEIo7bJAQiMmMoBCKudygEIs53KAQjRncoBCKiiygE=

由于 Google 没有回复 'Access-Control-Allow-Origin: *' - 客户端,并且在我有 origin:https://***.com 的请求中,我的 Chrome 会引发 CORS 错误。

在第二次测试中,使用 https://apigee.com/console/others 并请求 https://www.google.com ,apigee.com 似乎覆盖了标头并发送:

GET / HTTP/1.1
Host:
www.google.com
X-Target-URI:
https://www.google.com
Connection:
Keep-Alive

另外,从 DEV 控制台,我可以看到它执行服务器到服务器调用,因此没有客户端参与抛出 CORS,因此我通过 Google 页面获得响应。

更新:

关于 JSON API 请求,这里有一些来自 Google CloudPlatform 的关于 CORS 的有趣信息

注意:CORS 配置仅适用于 XML API 请求。对于 JSON API 请求,云存储返回 Access-Control-Allow-Origin 带有请求来源的标头。

因此,如果请求是从客户端执行的,则客户端不应抛出 CORS 错误,因为它获得的 Access-Control-Allow-Origin 与其发送的来源相同。

但是,不同的 API 和客户端可能会以不同的方式处理请求。因此,有时 Firefox 会抛出 CORS 而 Chrome 不会。

【讨论】:

如果我误解了,请纠正我。您说的是在您的第一次测试中,因为它是基于客户端的请求,它不起作用。第二次尝试有效,因为它是基于服务器的请求。考虑到这一点,我的问题仅针对客户请求。当您点击任何 API 时,即使是从 javascript(客户端启动),您也会得到 json 结果。我试图理解为什么会这样,而不是试图获得一个不起作用的 html 页面。 @Bojan 我用谷歌云平台的例子更新了我的答案,也许它会对基于 JSON 的 API 请求有所了解。 本质上,我认为标题Content-Type: application/json; 是我的客户端请求有效的原因是正确的。因为json类型的请求不会被CORS阻塞? 恕我直言,我认为这真的取决于 API 提供者以及它将哪些标头发送回客户端。例如,公共 API 可能希望允许来自不同来源的请求,而企业 API 将仅发回特定来源以确保只有允许的域才能执行请求。因此,即使企业 API 可能是公共的(不需要身份验证),如果您使用来自 randomdomain.com 的Content-Type: application/json 请求它 - 您的客户端仍然会抛出 CORS,因为它会得到源不匹配。有意义吗? 好吧,基本上你是说所有公共 API 都将 Access-Control-Allow-Origin 设置为 *。它是否正确?如果是这样,它不会为 XSS 攻击打开大门吗?

以上是关于了解页面响应的主要内容,如果未能解决你的问题,请参考以下文章

响应式设计1---响应式布局介绍

响应式设计丨必须了解的9项基本原则

常用Web服务器了解

Web基础了解版11-Ajax-JSON

网页设计中响应式具体怎么实现?

vue.js响应式原理解析与实现