Firebase 可调用函数:如何限制 CORS 来源

Firebase Callable Function: How to restrict CORS origin

Firebase 可调用函数默认支持 CORS。这很好,但它似乎默认允许来自任何来源的请求。如何将 CORS 请求限制到特定来源?

例如,这是一个预检请求示例(为演示目的而简化):

OPTIONS /callFunctionName HTTP/1.1
authority: us-central1-project-id.cloudfunctions.net
access-control-request-method: POST
access-control-request-headers: authorization,content-type
origin: https://foo.example.com
sec-fetch-mode: cors
sec-fetch-site: cross-site
sec-fetch-dest: empty

回复(简体):

HTTP/1.1 204 No Content
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: https://foo.example.com
Content-Length: 0

由于 Access-Control-Allow-Origin 响应请求源,浏览器将始终允许 CORS 请求。我该如何限制它?

很遗憾,您想要的是不可能的。可调用函数的响应 headers 仅允许 Content-Type 和一个可选的 charset。如果您需要控制和限制 CORS 或 protocol that deviates from what's implemented by Firebase Callable Functions, you should instead use a normal HTTP function and implement those details as mentioned in this answer.

的任何部分

要使用 HTTP 函数处理预检请求,您必须设置适当的 Access-Control-Allow-* 响应 headers.

这是处理预检请求的示例 nodejs 代码:

/**
 * HTTP function that supports CORS requests.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
exports.corsEnabledFunction = (req, res) => {
  // Set CORS headers for preflight requests
  // and caches preflight response for 3600s

  res.set('Access-Control-Allow-Origin', 'your-allowed-origin');
  // Allows GETs from your specified origin with the Content-Type header

  if (req.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    res.set('Access-Control-Allow-Methods', 'GET');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
  } else {
    res.send('Hello World!');
  }
};

或者,您可以使用 third-party 库来为您处理 CORS。

您也可以参考此documentation了解更多信息。

似乎提交了一个合并请求,允许我们将可调用函数的 cors 来源列入白名单:https://github.com/firebase/firebase-functions/pull/986

由于即将推出的 API 设计发生变化,PR 已关闭,但听起来 Firebase 团队正在努力添加此选项。