API CORS 标头不正确

您好,

我在将 Discourse 嵌入到我们的内网网站时遇到了问题。

API 文档指出,Discourse 请求需要包含“API-Key”和“Api-Username”这两个头部字段来进行身份验证并获取数据源。然而,预检检查(Pre-flight check)却显示允许的值是“User-API-Key”和“User-Api-Client-Id”。

在非浏览器环境中调用时,请求按预期工作。但在通过浏览器调用时,服务器却声称需要“User-API-Key”和“User-Api-Client-Id”。

我使用 Postman 测试了基本连接,其行为符合 Discourse 文档的说明。

如果我们按照文档传递头部字段,浏览器会因为预检检查而阻止请求,并抛出 Access-Control-Allow-Headers 的 CORS 错误。

如果我们传递服务器接受的头部字段,则会收到“未授权错误”,因为应用程序期望的是不同名称的值。

我尝试在 Docker 配置中添加头部字段,但似乎并未生效。CORS 已启用,且配置中 origin 设置为 ‘*’。

请问有人能提供建议吗?

谢谢,
Jessica

只是想问问关于上述问题是否还有更多信息?这是 bug 还是我操作有误?

谢谢,
Jessica

我们有两个不同的 API 认证系统,这可能会让人感到困惑。

这些是用于“管理员 API”的,相关说明可在 docs.discourse.org 上找到。该 API 并非设计用于从 JavaScript 客户端调用。

这些来自“用户 API”规范,可以从 JavaScript 客户端使用(因此支持 CORS)。更多详细信息请参见:User API keys specification

@david 我在使用 SSO,并希望用户在应用登出时同时从 Discourse 登出。目前我使用“管理员 API”通过 /users/by-external/${id}.json 获取用户 ID,但遇到了 CORS 错误。我不想仅为这个登出流程为所有用户启用“用户 API”。你有什么建议?

是什么在发起管理员 API 请求?是您客户端应用中的 JavaScript 吗?

您不应在 JavaScript 客户端中包含管理员 API,这意味着任何使用该客户端的人都能获得您网站的管理员访问权限。

是的,我的应用里用的是 JavaScript。我明白了。那有什么替代方案吗?我可以为单个用户添加一个“用户 API”,然后用它来代表所有用户发起调用吗?

如果您使用用户 API,应按用户单独处理。切勿共享密钥。

但最常见的做法是在您应用的服务器端进行处理。您的服务器可以使用管理员 API 密钥发送请求,这样既不会遇到跨域(CORS)问题,也能减少安全风险(前提是实施得当)。

谢谢 @david。这很有帮助,我会这样处理。再次感谢。

@david,我尝试实现一个后端解决方案,但当我调用 https://example.com/users/by-external/{EXTERNAL_USER_ID}.json?api_key={DISCOURSE_API_KEY}&api_username=system 时,收到的响应是登录页面的 HTML(我猜是重定向到了那里)。我已启用“需要登录”选项,而当我禁用该选项时,就能收到正确的 JSON 响应。我想保持该设置启用状态——有什么思路吗?

您需要使用请求头来传递 API 密钥和用户名。详情请查看 http://docs.discourse.org/。

问题解决了,再次感谢。:+1: