【问题标题】:Restricted by CORS policy even after enabling CORS on Express and Express gateway即使在 Express 和 Express 网关上启用 CORS 后,仍受 CORS 策略的限制
【发布时间】:2021-06-23 10:53:17
【问题描述】:

我正在使用Express Gateway 代理我的微服务。我正在使用Axios 从我的react 应用程序访问网关。但是,呼叫受到CORS Policy 的限制。我已经在快速网关和我的身份验证服务中启用了 CORS。我按照官方文档从link 为 Express Gateway 启用 CORS,从link 为身份验证服务(Express App)启用 CORS。这是我的代码。

Express Gateway config.yml

policies:
  - log
  - proxy
  - jwt
  - rate-limit
  - request-transformer
  - cors

pipelines:
  authPipeline: 
    apiEndpoints: 
      - auth
    policies: 
      -
        cors:
          -
            action:
              origin: '*'
              methods: 'HEAD,PUT,PATCH,POST,DELETE'
              allowedHeaders: ['Content-Type', 'Authorization']
      - 
        log: 
          action:
            message: 'auth ${req.method}'
      - 
        proxy:
          action: 
            serviceEndpoint: di

身份验证服务 app.js

const cors = require('cors');
// Enabling CORS
const corsOptions = {
  origin: '*',
  methods: ['POST', 'GET', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}
app.use(cors(corsOptions));

当我尝试使用 Insomnia(像 Postman 这样的客户端)时,我从服务器返回的标头如下图所示。

我在浏览器控制台中收到此错误。

Access to XMLHttpRequest at 'http://127.0.0.1:8080/api/v1/users/login' from 
origin 'http://localhost:3000' has been blocked by CORS policy: Response to 
preflight request doesnt pass access control check: No 'Access-Control- 
Allow-Origin' header is present on the requested resource.

我不确定我错过了什么。如果您需要其他任何东西,请告诉我,我会尽快提供。每一次试图解释我的案例有什么问题的尝试都非常感谢。

编辑:添加 API 调用 sn-p

const config = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
const body = JSON.stringify({ email, password });
const res = await axios.post('http://127.0.0.1:8080/api/v1/users/login', body, config);

【问题讨论】:

  • 为什么要使用origin:'*'?
  • 好吧,我只是想让它不管来源如何都能正常工作。这就是我使用它的原因。 @JamesMcLeod
  • 但是你不知道先验的可能起源的集合吗?这似乎违背了 CORS 的目的。你能用一个特定的值试试看它是否有效吗?
  • @JamesMcLeod 我只保留了我的反应服务器的端口后尝试过。我仍然得到同样的错误。

标签: node.js reactjs cors microservices express-gateway


【解决方案1】:

您的“方法”定义不正确。它需要采用 YAML 数组的形式:

methods: [ "HEAD", "PUT", "PATCH", "POST", "DELETE" ]

或者

methods:
- "HEAD"
- "PUT"
- "PATCH"
- "POST"
- "DELETE"

或者

methods:
- HEAD
- PUT
- PATCH
- POST
- DELETE

其他一切看起来都不错,尽管您可能希望将“origin”添加到 allowedHeaders 列表中。

更新 我已经对此做了一些进一步的测试,使用这个迷你快递服务器,然后在 Docker 上运行 API 网关和服务器(在 gateway.config.yml 中进行适当的主机名更改),一切正常,通过来自 localhost 的 curl 进行测试和也来自浏览器。

var express = require('express')
var app = express()

// Enabling CORS
const cors = require('cors');
const corsOptions = {
  origin: '*',
  methods: ['POST', 'GET', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}
app.use(cors(corsOptions));

function addPath(path) {
  app.use(path, function(req, res, next) {
    const response = `Hello from ${req.method} ${path}`;
    console.log(response);
    res.send(response);
  });
}

addPath('/api/v1/users/*');
addPath('/api/v1/*');

const port = 5000;
app.listen(port, function () {
  console.log(`Example app listening on port ${port}`)
})

我唯一可以建议的另一件事是在 gateway.config.yml 中的 cors 策略条目之前添加另一条日志消息 ,如下所示:

- 日志: 行动: 消息:“传入(身份验证):${req.method} ${req.path} 请求 IP:${req.ip} 来源 ${req.headers.origin}”

并检查原点的值。如果它不是未定义的,请尝试在代理策略之前添加以下响应转换器(当然,将响应转换器添加到可用策略列表中)。我不得不这样做一两次,但我忘记了必要的情况,所以这是在黑暗中拍摄。

  - response-transformer:
    - condition:
        name: expression
        expression: 'typeof req.headers.origin !== "undefined" && req.headers.origin === "http://localhost"'
      action:
        headers:
          add:
            access-control-allow-origin: '"http://localhost"'

【讨论】:

  • 我一次又一次地遇到同样的错误,即使我将值更改为origin: 'http://localhost:3000/'methods: ["HEAD", "PUT", "PATCH", "POST", "DELETE"]allowedHeaders: ["Content-Type", "Authorization"]。我将通过添加我如何调用 API 的 sn-p 来更新问题。请看一看。
  • 所有其他服务器端点都在工作吗?可能是浏览器问题?你试过卷曲吗?如果您有任何简单的 GET API 可以直接从浏览器中访问,请从浏览器地址栏尝试
  • 我尝试使用简单的 GET 从浏览器的地址栏中点击网关,它可以工作。但是当我尝试从反应中调用相同的端点时,它再次抛出相同的错误。我不确定出了什么问题。其他服务器端点工作正常。 @PranayNailwal
  • @VenkateshDharavath,从您的代码 sn-p 看起来好像您是在发布而不是获取;如果没有看到配置文件的其余部分,我们真的无能为力。你可以使用 curl 来访问它,同时使用 GET 和 POST 并查看其中一个/两者是否有效?
  • 好吧,我犯了一个愚蠢的错误,调试了很长时间。我只是把origin: 'http://localhost:3000\' 代替origin: 'http://localhost:3000'。尾部斜杠是造成问题的原因。我接受了这个答案,因为它帮助我进行了调试。谢谢@JamesMcLeod。
猜你喜欢
  • 2017-07-05
  • 2021-04-24
  • 2021-09-29
  • 2021-05-03
  • 2020-10-01
  • 2021-03-28
  • 1970-01-01
  • 2019-05-25
  • 2020-05-03
相关资源
最近更新 更多