为啥我总是得到一个不允许通配符 * 的 cors 错误,尽管我在服务器上指定了一个来源?

Posted

技术标签:

【中文标题】为啥我总是得到一个不允许通配符 * 的 cors 错误,尽管我在服务器上指定了一个来源?【英文标题】:Why do I always get a cors error that wildcard * is not allowed, although I specified a origin on the server?为什么我总是得到一个不允许通配符 * 的 cors 错误,尽管我在服务器上指定了一个来源? 【发布时间】:2019-11-19 02:22:45 【问题描述】:

我使用 Apollo Server 和 Apollo Client 创建了一个简单的 graphQL 聊天。

它还使用会话 cookie,所以我使用 npm 包 cors 初始化服务器,如下所示:

app.use(
  cors(
    credentials: true,
    origin: "http://localhost:3000"
  )
);

在客户端,我使用 apollo 客户端并像这样创建一个 http 链接:

const httpLink = new HttpLink(
  uri: "http://localhost:4000/graphql",
  credentials: "include"
);

所以我包含凭据并且服务器具有我的客户端的来源(确实是 http://localhost:3000 - create-react-app 默认值)。

当我想运行查询时,我在浏览器控制台中收到此错误:

从源“http://localhost:3000”获取“http://localhost:4000/graphql”的访问权限已被 CORS 策略阻止:响应中的“Access-Control-Allow-Origin”标头的值不能是通配符“* ' 当请求的凭据模式为 'include' 时。

为什么它说响应头设置了通配符 *,但在 cors 上我设置了特定的来源,所以它不应该是通配符对吗?

我在这里错过了什么?当然,我也重新启动了两台服务器。

当我这样设置客户端时:

const httpLink = new HttpLink(
  uri: "http://localhost:4000/graphql",
  credentials: "same-origin"
);

我没有收到来自 cors 的错误消息,但我没有收到来自服务器的 cookie。 Cookie 之所以有效,是因为在 graphQL Playground 上一切正常。

如需查看完整代码:https://github.com/SelfDevTV/graphql-simple-chat

【问题讨论】:

【参考方案1】:

问题解决了。

在我来自服务器的index.js 文件中。 下面几行我将 express 应用程序作为中间件应用到 apollo 服务器实例,如下所示:

server.applyMiddleware( app );

但这会覆盖我在上面设置的 cors 选项。

所以我必须这样称呼它:server.applyMiddleware( app, cors: false );

现在一切正常:)

【讨论】:

这只是关闭 cors。更好的解决方案是在您的 package.json "proxy": "http://localhost:4000/", 中为本地开发设置一个代理,它告诉您通过您的应用程序对代理端口 4000 做出反应以进行开发。对于生产,您需要将服务器和前端捆绑在一起 真的关掉了吗?因为这意味着凭据不会传递给客户端?所以cookies不会起作用,但他们会这样做吗?我是从 create-react-app 文件夹还是服务器的 package.json 设置你在 package.json 中提到的这个代理? 是的,cors: false 正在关闭 cors,这与凭据或 cookie 无关。这是一种安全保护,在这里可以更好地解释:medium.com/@baphemot/understanding-cors-18ad6b478e2b 至于代理,你把它放在你的 react package.json 中。 好的,当我设置这个代理时。接下来我到底要做什么。像这样使用 cors 包启用 cors:app.use( cors( credentials: true, origin: ["http://localhost:3000"] ) ); 并且还在 apollo 服务器实例上设置 cors:true?在客户端我可以设置credentials: "same-origin" ?像这样正确吗? 编辑: 不能以这种方式工作。 same-origin 有效,但没有 cookie。 include 与通配符相同的 cors 错误。 你不应该在任何一方显式地做任何事情,只需在反应端设置代理,它就会点击http://localhost:4000,就像它点击http://localhost:3000一样。以下是官方文档:facebook.github.io/create-react-app/docs/…【参考方案2】:

您可以改为告诉 Apollo 服务器如何配置 cors。

const corsOptions = 
  origin: "http://localhost:3000",
  credentials: true


server.applyMiddleware(
  app,
  cors: corsOptions
) 

那么你就可以完全消除 express cors 中间件了。

【讨论】:

这对我有用。我认为这应该是公认的答案。 当我使用http://localhost:3000true 作为我的来源时,它起作用了,但当我在网址末尾添加*//* 时,它就不行了,例如http://localhost:3000/。我还在我的env.dev文件中添加了这个作为变量:CLIENT_URL=http://localhost:3000,然后通过origin: process.env.CLIENT_URL将它加载到服务器索引中,效果很好

以上是关于为啥我总是得到一个不允许通配符 * 的 cors 错误,尽管我在服务器上指定了一个来源?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在使用 location.href 时总是被 CORS 阻止

如何修复“CORS 协议不允许同时指定通配符(任何)来源和凭据”错误

使用Azure功能启用CORS通配符子域

如何使用通配符来允许特定域 CORS?

API 网关 CORS 问题

为啥浏览器允许设置一些没有 CORS 的标头,但不允许设置其他标头?试图避免预检