【问题标题】:Recaptcha3 , Javascript, and Firebase backend problemRecaptcha3、Javascript 和 Firebase 后端问题
【发布时间】:2021-08-25 13:20:59
【问题描述】:

我对 Javascript 比较陌生,所以请多多包涵。我已经用谷歌搜索并测试了一天没有成功,所以我需要向社区寻求帮助。我正在尝试使用 Recaptcha3 在我的 React JS 网站上验证联系表单的内容。我根据表单的内容(电子邮件、姓名)看似正确地收到了令牌,但是将令牌发送到我的后端(Firebase 函数)不起作用。我不断崩溃:

....
2021-08-25T03:45:00.892Z I sendRecaptcha: token undefined
2021-08-25T03:45:01.198Z ? sendRecaptcha: { success: false, error: 'response not valid' }
2021-08-25T03:45:01.199Z ? sendRecaptcha: Unhandled rejection
2021-08-25T03:45:01.246Z ? sendRecaptcha: { success: false, error: 'captcha_error' }
2021-08-25T03:45:01.252056348Z D sendRecaptcha: Function execution took 374 ms, finished with status: 'crash'

在表单上按下提交后我的代码触发了云功能sendRecaptcha

const handleSubmit = event => {
        event.preventDefault()

        const apiString = 'https://xxxx.cloudfunctions.net/sendRecaptcha'
        setLoading(true);
        window.grecaptcha.ready(() => {
            window.grecaptcha.execute(SITE_KEY, {action: 'form'})
                .then(function(token) {
                    console.log("TOKEN: ",token);

                    Axios.get(`${apiString}?token=${token}`)
                        .then(function (response) {
                            const score = response.data.score;
                            console.log("score: ", score);
                            sendVerifiedContent()

                            $("#contact").unbind('submit').submit();
                        })
                        .catch(function (error) {
                            console.log("error: ", error);
                        });
                });
        });
    }

我的 index.js 云函数(Firebase 函数):

const USER_ERROR_CODES = ['missing-input-response', 'invalid-input-response']

exports.sendRecaptcha = functions.https.onRequest(async (req, res) => {
    //res.set('Access-Control-Allow-Origin', functions.config().recaptcha.origin);
    res.set('Access-Control-Allow-Origin', '*')
    res.set('Access-Control-Allow-Methods', 'GET, PUT, POST, OPTIONS')
    res.set('Access-Control-Allow-Headers', '*')

    const secret = functions.config().recaptacha.key;
    functions.logger.log("SECRET:", secret);

    const token = res.query.body;
    functions.logger.log("token", token);

    try {
        let result = await axios({
            method: 'post',
            url: 'https://www.google.com/recaptcha/api/siteverify',
            params: {
                secret:secret,
                response:token,
            }
        });
        let data = result.data || {};
        if(!data.success){
            throw({
                success: false,
                error: 'response not valid'
            })
        }
    }catch(err){
        console.log(err);
        throw err.response ? err.response.data : {success: false, error: 'captcha_error'}
    }
})

window.grecaptcha.executefunction 完成时,我看到了令牌,它看起来像这样(看起来不错):

03AGdBq255ghLC0DOUleaz71srZlcYWCiVlR-aldGXQZ6L2D-wIkJb5V_NDh66AYWsERT0w9hFLIt5nVikfjigufJvA2phS_ns-6X8YAza0S-nCS0RUPx1IgJBQUZ1Vl-Cc5AfuOcavSzCicNtSHAcLLXZPY-dY3PbIo-jzelpBelyfD8RGB8dKrWreP2cCfgitjs24xtX8J94ED3WC4DzQKCbfvEEQrEoAHWY2rueU2lDfflBybpz5u7lXccd_zDTORy9WEiHQBK2vEuEuJXZ-85mLP1acI03I1lOXpm_uLBTO3YJMpXc5Jq-4eRO4vDvox23YxfKYgXQd5UZPvkWQWq7sv_9ANUZK1w28LeK7aZO-9KUmGMmm3IFfaOKYrggVAIoEq8ex3unGZTxwq4ZnrYzYhGAx02PAmC5UQEjbBHLDStfYaaLHh8

但是,一旦我的云函数被调用,我就无法从 req.query.token 获取令牌(functions.logger.log("token", token) 的输出未定义)并且函数的其余部分崩溃。

我确定这是一个初学者的问题,但希望得到一些帮助。

更新 我遵循了@Dharmaraj 的建议,并且能够在我的云功能中正确获取令牌。该功能似乎卡住并超时。我的代码还有什么需要改进的地方吗?

D sendRecaptcha: Function execution took 60011 ms, finished with status: 'timeout'

【问题讨论】:

  • 现在有Firebase App Check,对于网络应用程序而言,它基本上似乎是 reCaptcha v3(或您的自定义提供程序)的包装器。这可能比直接使用 reCaptcha 更容易使用。您可以通过admin.appCheck().verifyToken(appCheckToken) 验证应用检查令牌,这似乎比向 reCaptcha 发出 POST 请求更容易。

标签: javascript node.js firebase google-cloud-functions recaptcha


【解决方案1】:

query 属性存在于request 对象上,而不是response。要访问查询参数,请将您的代码重构为:

const token = req.query.token;
// alternatively using object destructuring
const {token} = req.query

req.query 将是所有查询参数的对象。例如,如果您的网址是https://domain.tld?q1=hello&q2=world,则req.query 将是{q1: "hello", q2: "world"}


您应该通过发送响应来终止您的 HTTP 函数,否则它将继续运行 60 秒(或您的最大超时持续时间)并最终以该超时错误结束:

try {
  if (!data.success) {
    throw ({
      success: false,
      error: 'response not valid'
    })
  }
  res.status(200).json({data: data})
} catch (e) {
  console.log(e)
  res.status(500).json({error: e})
}

来自documentation

确保所有 HTTP 函数都正确终止。通过正确终止函数,您可以避免因运行时间过长的函数而产生过多费用。使用 res.redirect()、res.send() 或 res.end() 终止 HTTP 函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    相关资源
    最近更新 更多