【问题标题】:HTTP request working from Postman and Node but not React来自 Postman 和 Node 的 HTTP 请求,但不是 React
【发布时间】:2021-08-17 11:27:18
【问题描述】:

Stack Overflow 上有几个类似的问题,提出的解决方案都没有奏效,所以我将介绍这个案例以及我尝试过的方法。

我有一个托管在 Cloud Run 上的服务器应用程序,只能使用请求授权标头中的适当 Bearer 令牌来访问它。我已经尝试通过 Postman 和来自本地 Nodejs 服务器的 Axios 请求以及 Authorization 标头来访问它,并且效果很好。使用 React(特别是 create-react-app),我收到以下错误:Access to XMLHttpRequest at 'https://myserver-lhp5a9xp5a-ue.a.run.app/api/rules' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

在服务器端,当传递了不正确的授权令牌时,我收到了 Cloud Run 给出的 403 错误。此外,当我允许从 Cloud Run 端进行未经身份验证的访问时(因此不再需要 Authorization 标头),请求工作正常,因此看起来这确实是 Authorization 标头的问题而不是 CORS。

此外,我正在服务器端处理 CORS。这是我的服务器端代码:

var express = require('express');
var router = express.Router();
const cors = require('cors');

router.options('/api/rules', cors());
router.get('/api/rules', cors(), (req, res, next) => {
  res.status(200).send()
});

这是我的 React 代码:

const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_API_BASE_URL
});

const buttonClickHandler = async (event) => {
  const resp = await axiosInstance.get('/api/rules'
   , {
     headers: {
       'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsImtpZ...' // I used this token within the same minute when trying the request via Postman or from my Nodejs app, so a token expiry isn't the issue.
     }
   }
  )
  console.log(resp.data)
}

这是我目前尝试过的:

  • 使用 fetch 而不是 axios - 同样的错误
  • 使用相同的令牌,在相同的 5 秒内,从 Postman 或 Nodejs 服务器发送请求 - 工作正常。
  • 使用 axios 拦截器设置授权 - 同样的错误
  • 删除授权周围的单引号 - 相同的错误
  • 改为将请求发送到我的 Nodejs 服务器,并对标头执行 console.log 以确保正确传递了授权令牌(确实如此)
  • 不使用 axios 实例,而是在请求中拼写完整的 URL - 同样的错误
  • 在我的 Cloud Run 服务器上尝试不同的端点 - 同样的错误
  • 部署我的 React 应用程序以从 https 端点提供服务并从那里发送请求 - 相同的错误
  • 在标题中添加Accept: '*/*'
  • 在标题中添加'Accept': '*/*'
  • 在标题中添加'Content-Type': 'application/json'
  • 以上三点的所有组合

【问题讨论】:

  • 你是如何使用认证中间件的?有类似router.get('/api/rules', **auth**, cors(), (req, res, next) => { 的东西吗?

标签: node.js reactjs authorization google-cloud-run


【解决方案1】:

经过一番挖掘,我找到了答案,感谢 @aniket-kolekar 为我指明了正确的方向。

当 Postman 或 Nodejs 服务器查询像 GETPOSTPUTDELETE 这样的端点时,它们会在不先检查 OPTIONS 的情况下发送调用。 Create-React-App 可以。

我查询的服务托管在 Cloud Run 上,不允许未经身份验证的调用。因此,当我在进行GET 调用时包含授权标头时,它并没有包含在飞行前OPTIONS 调用中。其实CORS prevents auth headers from being included in an OPTIONS call

Cloud Run PM 在this post 中回复说这是 Cloud Run 的一个已知问题。我现在解决它的方法是在 Cloud Run 上托管两项服务 - 一项不需要身份验证,并有效地充当代理服务器,将来自客户端服务的调用路由到受屏蔽的服务器服务。

【讨论】:

  • 很高兴我能帮上忙
【解决方案2】:

TLDR;

  • CORS 是一种内置在 Web 浏览器中的机制。这不是 UI 代码问题。
  • 要修复 CORS 问题,您需要在 API(服务器)端进行更改。

这里是幕后工作:

浏览器:发送OPTIONS 调用以检查服务器类型并在向 API 端点发送任何新请求之前获取标头。它在哪里检查Access-Control-Allow-Origin。考虑到这一点,Access-Control-Allow-Origin 标头仅指定允许所有 CROSS ORIGINS,尽管默认情况下浏览器将只允许相同的来源。

邮递员:直接发送GETPOSTPUTDELETE等请求,不检查服务器类型并使用@987654329获取标头Access-Control-Allow-Origin @调用服务器。

您必须在服务器中配置 Access-Control-Allow-Origin 标头才能解决 CORS 问题。

【讨论】:

  • 谢谢!但不幸的是,我认为这不是答案:1)我的服务器端已经有 OPTIONS 和 cors() 处理(好点 - 将在我的问题中添加该代码)2)当我允许在服务器端进行未经身份验证的调用时(原则上,与 CORS 无关),请求工作正常
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-28
  • 2019-01-19
  • 2014-12-07
  • 1970-01-01
  • 2022-09-17
  • 2021-04-11
相关资源
最近更新 更多