栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaScript尝试从REST API获取数据时,请求的资源上没有“ Access

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaScript尝试从REST API获取数据时,请求的资源上没有“ Access

该答案涉及很多领域,因此分为三个部分:

  • 如何使用CORS代理来解决 “无访问权限-允许-来源标头” 问题
  • 如何避免CORS飞行前
  • 如何解决 “ Access-Control-Allow-Origin标头一定不能为通配符”的 问题

如何使用CORS代理来解决 “无访问权限-允许-来源标头” 问题

如果您不控制服务器,则您的前端Javascript代码正在向其发送请求,而该服务器的响应问题仅在于缺少必要的

Access-Control-Allow-Origin
标头,那么您仍然可以使事情顺利进行-通过通过CORS代理。为了展示它是如何工作的,首先这里是一些不使用CORS代理的代码:

const url = "https://example.com"; // site that doesn’t send Access-Control-*fetch(url).then(response => response.text()).then(contents => console.log(contents)).catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

造成该

catch
区块被打的原因是,浏览器阻止该代码访问从返回的响应
https://example.com
。而浏览器这样做的原因是,响应缺少
Access-Control-Allow-Origin
响应头。

现在,这是完全相同的示例,只是在其中添加了CORS代理:

const proxyurl = "https://cors-anywhere.herokuapp.com/";const url = "https://example.com"; // site that doesn’t send Access-Control-*fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com.then(response => response.text()).then(contents => console.log(contents)).catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

注意:如果在尝试https://cors-
anywhere.herokuapp.com时关闭或不可用,请参见下文,了解如何在2-3分钟内在Heroku上部署自己的CORS
Anywhere服务器。

上面的第二个代码段可以成功访问响应,因为采用请求URL并将其更改为https://cors-
anywhere.herokuapp.com/https://example.com(只需在其前面加上代理URL)即可请求通过该代理取得,然后:

  1. 将请求转发到
    https://example.com
  2. 收到来自的回复
    https://example.com
  3. Access-Control-Allow-Origin
    标头添加到响应中。
  4. 将带有添加的标头的响应传递回请求的前端代码。

然后,浏览器允许前端代码访问响应,因为带有

Access-Control-Allow-Origin
响应标头的响应就是浏览器看到的内容。

您可以使用https://github.com/Rob--W/cors-anywhere/中的代码轻松运行自己的代理。
您还可以使用5条命令在2-3分钟内轻松地将自己的代理部署到Heroku中:

git clone https://github.com/Rob--W/cors-anywhere.gitcd cors-anywhere/npm installheroku creategit push heroku master

运行这些命令后,您将最终在以下位置运行自己的CORS Anywhere服务器。因此,不要在您的请求URL前面加上

https://cors-anywhere.herokuapp.com
,而是在您自己的实例的URL 前面加上前缀。

因此,如果您尝试使用https://cors-anywhere.herokuapp.com时发现它已关闭 (有时会 关闭
),则考虑获取一个Heroku帐户(如果您尚未使用)并拿2或花费3分钟完成上述步骤,以在Heroku上部署您自己的CORS Anywhere服务器。

无论您是运行自己的网站还是使用https://cors-anywhere.herokuapp.com或其他开放式代理,即使该请求触发了浏览器执行CORS预检

OPTIONS
请求,该解决方案仍然可以使用-
因为在这种情况下,代理还会发回使预检成功所需的
Access-Control-Allow-Headers
Access-Control-Allow-Methods
标头。


如何避免CORS飞行前

问题中的代码由于发送了

Authorization
标头而触发了CORS预检。

https://developer.mozilla.org/zh-
CN/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

即使没有这些,

Content-Type: application/json
标题也将触发预检。

“预检”的含义是:在浏览器尝试输入

POST
问题代码之前,它将首先向
OPTIONS
服务器发送请求-
确定服务器是否选择接收
POST
包含
Authorization
Content-Type: application/json
标头的跨域。

它与一个小的curl脚本一起使用时效果很好-我得到了数据。

要使用进行正确的测试

curl
,您需要模拟
OPTIONS
浏览器发送的预检请求:

curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000"     -H 'Access-Control-Request-Method: POST'     -H 'Access-Control-Request-Headers: Content-Type, Authorization'     "https://the.sign_in.url"

https://the.sign_in.url
替换为您的实际
sign_in
网址。

浏览器需要从该

OPTIONS
请求中看到的响应必须包含以下标头:

Access-Control-Allow-Origin:  http://127.0.0.1:3000Access-Control-Allow-Methods: POSTAccess-Control-Allow-Headers: Content-Type, Authorization

如果

OPTIONS
响应中不包含这些标头,则浏览器将在那里停止,甚至从不尝试发送
POST
请求。另外,响应的HTTP状态代码必须为2xx,通常为200或204。如果是其他任何状态代码,浏览器将在此处停止。

问题中的服务器正在

OPTIONS
使用501状态代码来响应请求,这显然意味着它试图表明它未实现对
OPTIONS
请求的支持。在这种情况下,其他服务器通常会以405“不允许使用方法”状态代码进行响应。

因此

POST
,如果服务器
OPTIONS
使用405或501或200或204以外的任何其他值响应该请求,或者如果未响应必要的响应,则永远无法从前端Javascript代码直接向该服务器发出请求响应头。

避免触发该案件的预检的方法是:

  • 如果服务器不需要
    Authorization
    请求标头,而是(例如)依赖于嵌入在
    POST
    请求正文中或作为查询参数的身份验证数据
  • 如果服务器不要求
    POST
    主体具有
    Content-Type: application/json
    媒体类型,而是接受名为参数(或其他参数)的
    POST
    主体
    application/x-www-form-urlenpred
    ,其参数为
    json
    JSON数据

如何解决 “ Access-Control-Allow-Origin标头一定不能为通配符”的 问题

我收到另一条错误消息:

当请求的凭据模式为“ include”时,响应中“ Access-Control-Allow-Origin”标头的值不得为通配符“
*”。因此,不允许访问源’ http://127.0.0.1:3000
‘。XMLHttpRequest发起的请求的凭据模式由withCredentials属性控制。

对于包含凭据的请求,如果

Access-Control-Allow-Origin
响应标头的值为,浏览器将不允许您的前端Javascript代码访问响应
*
。相反,在这种情况下,值必须与前端代码的来源完全匹配
http://127.0.0.1:3000

如果控制要向其发送请求的服务器,则处理这种情况的一种常用方法是将服务器配置为采用

Origin
请求标头的值,并将其回显/反射回
Access-Control-Allow-Origin
响应标头的值。例如,使用nginx:

add_header Access-Control-Allow-Origin $http_origin

但这只是一个例子。其他(网络)服务器系统提供了类似的方法来回显原始值。


我正在使用Chrome。我也尝试过使用Chrome CORS插件

Chrome CORS插件显然只是将

Access-Control-Allow-Origin:*
标头注入浏览器看到的响应中。如果该插件更聪明,它将采取的措施是将该假
Access-Control-Allow-Origin
响应标头的值设置为您的前端Javascript代码的实际来源
http://127.0.0.1:3000

因此,即使进行测试,也请避免使用该插件。这只是分心。如果您想测试从服务器获得的响应,而没有浏览器对其进行过滤,则最好使用

curl -H
上述方法。


至于

fetch(…)
问题中请求的前端Javascript代码:

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');headers.append('Access-Control-Allow-Credentials', 'true');

删除这些行。该

Access-Control-Allow-*
头是 响应 头。您永远不想在请求中发送它们。唯一的效果就是触发浏览器进行预检。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/380716.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号