【问题标题】:How to implement google reCaptcha without inline script?如何在没有内联脚本的情况下实现 google reCaptcha?
【发布时间】:2020-12-24 12:41:19
【问题描述】:

期望的行为

在我的 webpack 捆绑 js 文件中加入 reCaptcha JavaScript 代码,而不是通过内联脚本标签。

实际行为

我在 Chrome 开发工具中收到此错误:

Uncaught ReferenceError: grecaptcha is not defined

我的尝试

以下inline 实现有效,我一直在使用these docs for reference

但是,我必须将 unsafe-inline 添加到我的 script-src 内容安全策略中才能允许内联脚本运行。更具体地说,这是通过onLoadCallback 函数实现explicit rendering 所必需的。

Google 有一个FAQ about CSP and reCaptcha,但它只适用于automatic rendering,没有回调函数或defined parameters

我宁愿不必使用内联脚本。

index.html

<head>
    <script type="text/javascript">
    var onloadCallback = function() {
        grecaptcha.render('g-recaptcha', {
            'sitekey': '******',
            'size': 'compact'
        });
    };
    </script>
</head>
<body>
    <div id="g-recaptcha"></div>
    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
</body>
</html>

但是,当我尝试像这样将 JS 添加到我的 entry.js 文件中时(停止使用内联脚本):

index.html

<head>
    <script type="module" src="/js/bundle.js"></script>
    <script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
</head>
<body>
    <div id="g-recaptcha"></div>
</body>
</html>

entry.js

const onloadCallback = () => {
    grecaptcha.render('g-recaptcha', {
        'sitekey': '******',
        'size': 'compact',
        'data-callback': 'ok-you-can-submit-the-form',
        'data-expired-callback': 'you-have-to-click-recaptcha-again',
        'data-error-callback': 'something-went-wrong-please-try-again'
    });
}

$(document).ready(function() {

    onloadCallback();

}

我在 Chrome 开发工具中遇到错误:

Uncaught ReferenceError: grecaptcha is not defined

所以我猜这是因为bundle.js 不知道&lt;head&gt; 部分中定义的recaptcha 脚本或其相关变量。

如何在不使用内联脚本范例的情况下实现 google reCaptcha?

编辑

我认为 Google 建议使用 nonce-based approach(在 this SO answer 中也建议)仅在您使用 automatic rendering(只需要 &lt;script src="****"&gt; 标记)时才有效。

如果您像我一样使用explicit rendering,这需要内联定义回调函数,那么我认为nonce 方法行不通。

【问题讨论】:

  • 您需要为此使用适当的 npm 构建,通常的 recaptcha CDN 构建不适用于 webpack

标签: javascript jquery recaptcha


【解决方案1】:

只是发布最后对我有用的东西。

使用reCAPTCHA v3

index.html头:

<script src="https://www.google.com/recaptcha/api.js?render=*******"></script>

点击事件:

grecaptcha.ready(function() {
    grecaptcha.execute('*******', { action: 'submit_entry' }).then(function(token) {
        parameters.token = token;
        ajax_api_entries_post(parameters);
    });
});

从服务器验证谷歌令牌:

var token = req.body.token;
var url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;
var response = await fetch(url);
var response_json = await response.json();

var score = response_json.score;

// see: https://developers.google.com/recaptcha/docs/v3#interpreting_the_score
if (score >= 0.5) { ...

helmet配置:

app.use(
    helmet({
        contentSecurityPolicy: {
            directives: {
                defaultSrc: ["'self'"],
                scriptSrc: ["'self'", "https://maps.googleapis.com", "https://www.google.com", "https://www.gstatic.com"],
                connectSrc: ["'self'", "https://some-domain.com", "https://some.other.domain.com"],
                styleSrc: ["'self'", "fonts.googleapis.com", "'unsafe-inline'"],
                fontSrc: ["'self'", "fonts.gstatic.com"],
                imgSrc: ["'self'", "https://maps.gstatic.com", "https://maps.googleapis.com", "data:", "https://another-domain.com"],
                frameSrc: ["'self'", "https://www.google.com"]
            }
        },
    })
);

【讨论】:

    猜你喜欢
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    相关资源
    最近更新 更多