在 Firebase 函数中验证 reCAPTCHA v3 会导致 CORS 问题
Verifying reCAPTCHA v3 in Firebase Function causes CORS Issue
我有以下代码验证我的 Firebase 函数中的 Google reCAPTCHA v3 导致了 CORS 问题:
const functions = require('firebase-functions');
const nodemailer = require("nodemailer");
const express = require("express");
const cors = require("cors");
const request = require('request');
const serverApi = express();
api.use(cors({ origin: true }));
function verifyCaptcha(token, returnData) {
// Put your secret key here.
var secretKey = functions.config().recaptcha.secretkey;
var verificationUrl = "https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + token;
// Note here: External network call to google.com
request(verificationUrl, function (error, response, body) {
body = JSON.parse(body);
// Success will be true or false depending upon captcha validation.
if (!body.success) {
body['status'] = false;
body['errSource'] = "recaptcha";
body['message'] = "Failed to pass captcha verification.";
} else {
body['status'] = true;
body['message'] = "Successfully passed captcha verification!";
};
console.log(`Google returns: ${JSON.stringify(body)}`);
returnData(body);
});
};
api.post("/api/service-name", (req, res) => {
if (!req.body['g-recaptcha-response']) {
return res.send({ "status": false, "errSource": "recaptcha", "message": "Client-side reCAPTCHA token not found." });
};
const recaptchaToken = req.body['g-recaptcha-response'];
verifyCaptcha(recaptchaToken, function (result) {
if (result.status == false) {
return res.send(result);
};
// My business logics here.
});
});
exports.api = functions.https.onRequest(api);
我注意到在我的 Firebase 函数中删除 reCAPTCHA v3 验证请求后,我的本地主机使用 $.ajax()
调用 "/api/service-name"
不再有 CORS 问题。这是因为以下 Firebase 函数日志让我想起了 "External network is not accessible":
Billing account not configured. External network is not accessible and quotas are severely limited.
Configure billing account to remove these restrictions
我的问题是:有没有办法让我的服务器端 reCAPTCHA 验证正常工作,而不会导致这个 CORS 问题,"Billing account not configured" 可以避免这个问题?谢谢!
更新:
捕获到执行验证的 request()
错误后,我得到以下错误:
{errno: "EAI_AGAIN", code: "EAI_AGAIN", syscall: "getaddrinfo", hostname: "www.google.com", host: "www.google.com", …}
另外,这个错误处理后,CORS问题没有了,但是reCAPTCHA还是无法验证。知道是什么原因造成的吗?再次感谢!
现已确认,在Google Cloud Console启用计费后,上述问题已得到解决。 实际上不是本地主机和 Firebase Functions/Hosting 之间的 CORS 问题(尽管 Chrome 浏览器作为 CORS 相关错误消息返回),实际上是 在令牌验证过程中,Firebase 函数向 Google reCAPTCHA api 发出的 HTTP 请求。由于计费帐户未链接到函数所在的 Firebase 项目,任何来自任何 Firebase 函数的任何请求到任何 外部网络资源,包括 Google reCAPTCHA,都将被拒绝以下错误:
HTTP 请求错误:
{errno: "EAI_AGAIN", code: "EAI_AGAIN", syscall: "getaddrinfo", hostname: "www.google.com", host: "www.google.com", …}
在 GCP 启用计费并将计费帐户链接到特定的 Firebase 项目后,请求 Google reCAPTCHA 验证将成功(如果令牌有效)而不会出现上述错误。但是,您的 免费 Spark 等级 Firebase 帐户将自动升级 至 Blaze 计划 -- 即付即用去吧。
我有以下代码验证我的 Firebase 函数中的 Google reCAPTCHA v3 导致了 CORS 问题:
const functions = require('firebase-functions');
const nodemailer = require("nodemailer");
const express = require("express");
const cors = require("cors");
const request = require('request');
const serverApi = express();
api.use(cors({ origin: true }));
function verifyCaptcha(token, returnData) {
// Put your secret key here.
var secretKey = functions.config().recaptcha.secretkey;
var verificationUrl = "https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + token;
// Note here: External network call to google.com
request(verificationUrl, function (error, response, body) {
body = JSON.parse(body);
// Success will be true or false depending upon captcha validation.
if (!body.success) {
body['status'] = false;
body['errSource'] = "recaptcha";
body['message'] = "Failed to pass captcha verification.";
} else {
body['status'] = true;
body['message'] = "Successfully passed captcha verification!";
};
console.log(`Google returns: ${JSON.stringify(body)}`);
returnData(body);
});
};
api.post("/api/service-name", (req, res) => {
if (!req.body['g-recaptcha-response']) {
return res.send({ "status": false, "errSource": "recaptcha", "message": "Client-side reCAPTCHA token not found." });
};
const recaptchaToken = req.body['g-recaptcha-response'];
verifyCaptcha(recaptchaToken, function (result) {
if (result.status == false) {
return res.send(result);
};
// My business logics here.
});
});
exports.api = functions.https.onRequest(api);
我注意到在我的 Firebase 函数中删除 reCAPTCHA v3 验证请求后,我的本地主机使用 $.ajax()
调用 "/api/service-name"
不再有 CORS 问题。这是因为以下 Firebase 函数日志让我想起了 "External network is not accessible":
Billing account not configured. External network is not accessible and quotas are severely limited.
Configure billing account to remove these restrictions
我的问题是:有没有办法让我的服务器端 reCAPTCHA 验证正常工作,而不会导致这个 CORS 问题,"Billing account not configured" 可以避免这个问题?谢谢!
更新:
捕获到执行验证的 request()
错误后,我得到以下错误:
{errno: "EAI_AGAIN", code: "EAI_AGAIN", syscall: "getaddrinfo", hostname: "www.google.com", host: "www.google.com", …}
另外,这个错误处理后,CORS问题没有了,但是reCAPTCHA还是无法验证。知道是什么原因造成的吗?再次感谢!
现已确认,在Google Cloud Console启用计费后,上述问题已得到解决。 实际上不是本地主机和 Firebase Functions/Hosting 之间的 CORS 问题(尽管 Chrome 浏览器作为 CORS 相关错误消息返回),实际上是 在令牌验证过程中,Firebase 函数向 Google reCAPTCHA api 发出的 HTTP 请求。由于计费帐户未链接到函数所在的 Firebase 项目,任何来自任何 Firebase 函数的任何请求到任何 外部网络资源,包括 Google reCAPTCHA,都将被拒绝以下错误:
HTTP 请求错误:
{errno: "EAI_AGAIN", code: "EAI_AGAIN", syscall: "getaddrinfo", hostname: "www.google.com", host: "www.google.com", …}
在 GCP 启用计费并将计费帐户链接到特定的 Firebase 项目后,请求 Google reCAPTCHA 验证将成功(如果令牌有效)而不会出现上述错误。但是,您的 免费 Spark 等级 Firebase 帐户将自动升级 至 Blaze 计划 -- 即付即用去吧。