如何在nuxt中使用google recaptcha?

How to use google recaptcha in nuxt?

我正在使用 nuxt 并且想使用这个库:https://github.com/nuxt-community/recaptcha-module. But I don't understand how to verify that the user has passed the check. The example doesn't tell me too much (https://github.com/nuxt-community/recaptcha-module/blob/master/example/v3/pages/index.vue)。有人可以告诉我如何正确地做吗?

这个例子只是故事的一半。它 returns client-side 上的 Recaptcha V3 令牌。

然后必须将其发送到服务器端并使用您的密钥进行验证。

这是通过向 URL 发送一个 post 来完成的:

const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${token}`;

您不想在客户端允许此密钥。

要在 Nuxt 中实现这一点,假设版本为 2.13+,您可以在 nuxt 配置中使用 privateRuntimeConfig

这将允许您 link 仅在服务器端注入 .env 文件。

对于这个用例,像这样的 privateRuntimeConfig 就足够了:

privateRuntimeConfig: {
    secretKey: process.env.GOOGLE_SECRET
}

完成此操作后,您将能够在 Nuxt 应用程序中作为 this.$config 的一部分访问这些变量 - 在本例中 this.$config.secretKey 调用 Recaptcha 验证端点时。

更多信息check out the Nuxt blog

在您的 nuxt.config.js

中使用 https://github.com/nuxt-community/recaptcha-module
modules: [
  '@nuxtjs/recaptcha',
],

recaptcha: {
  hideBadge: true,
  siteKey: "ABC...", // Better would be from 'process.env.API_KEY' and with '.env' file
  version: 2, // Or 3
},

请记住 modulesbuildModules 不同(有时由于相似的命名可能会混淆)。

这是 ReCaptcha V3 的有效实现:

package.json

  "dependencies": {
    "@nuxtjs/axios": "^5.13.6",
    "@nuxtjs/recaptcha": "^1.0.4",
    "h3": "^0.3.9",
  },

注意 h3 版本。我无法让它与更新版本一起使用,因为该库已转换为 EJS/mjs 和 TypeScript,这与 Nuxt 冲突。转译 h3 没有修复它。它可能适用于 Nuxt V3+。

nuxt.config.js

  modules: [
    ['@nuxtjs/recaptcha', {
      siteKey: process.env.RECAPTCHA_SITE_KEY,
      version: 3,
    }],
  ],

  serverMiddleware: [
    { path: '/api/check-token', handler: '~/middleware/recaptcha' },
  ],

middleware/recaptcha.js

import { useBody } from 'h3';
import axios from 'axios';

export default async (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  try {
    const { token } = await useBody(req);

    if (!token) {
      res.end(
        JSON.stringify({
          success: false,
          message: 'Invalid token'
        })
      );
      return;
    }

    axios.get(`https://www.google.com/recaptcha/api/siteverify?secret=${process.env.RECAPTCHA_SECRET_KEY}&response=${token}`).then((answer) => {
      if (answer.status) {
        res.end(
          JSON.stringify({
            success: true,
            message: 'Token verified'
          })
        );
      } else {
        res.end(
          JSON.stringify({
            success: false,
            message: 'Invalid token'
          })
        );
      }
    });
  } catch (e) {
    console.log('ReCaptcha error:', e);
    res.end(
      JSON.stringify({
        success: false,
        message: 'Internal error'
      })
    );
  }
};

.env

RECAPTCHA_SITE_KEY=gosei478htosvei478tvoei478tvge
RECAPTCHA_SECRET_KEY=ios47eos487t6es4897gtv6es487

index.vue

async mounted() {
    try {
        await this.$recaptcha.init();
    } catch (err) {
        throw new Error(`index# Problem initializing ReCaptcha: ${err}.`);
    }
},

beforeDestroy() {
    this.$recaptcha.destroy();
},

methods: {
    async submitContactForm() {
        try {
            const token = await this.$recaptcha.execute('contact')

            const formData = {
                email: this.contactForm.email,
                firstname: name.firstName,
                lastname: name.lastName,
                phone: this.contactForm.phone,
                band_name: this.contactForm.band_name,
                initial_message: this.contactForm.message,
            }

            // note: use POST request
            const recaptcha = await this.$axios.post('/api/check-token', { token });

            console.log('recaptcha', recaptcha.data);

            if (recaptcha.data.success) {
                const result = await this.$axios.post(process.env.CONTACT_FORM_API, formData);


                // cleanup logic
            } else {
                // handle error case
            }
        } catch (err) {
            // handle errors
        }
    },
},

您可以在此处阅读更多内容:https://www.npmjs.com/package/@nuxtjs/recaptcha

注意它所说的部分

Server Side When you send data + token to the server, you should verify the token on the server side to make sure it does not requested from a bot. You can find out how to verify token on the server side by looking at the server middleware inside v2 example. (The server side is same for both versions)

上面的server-side中间件就出自那里。使用我建议的 h3 版本很重要,因为您需要它来访问 useBody(req)。我尝试了几个小时来寻找另一种方法来阅读请求正文,但事实证明这太难了。在较新版本的 Nuxt 中,您的结果可能会有所不同。我建议尝试使用最新版本的 h3,如果在构建应用程序时失败并出现错误,请尝试使用旧版本。

暴露 ReCaptcha 密钥非常重要,此解决方案将其保密在 server-side.

更好的解决方案可能是使用您的实际服务器并创建一个端点来验证 ReCaptcha 令牌。假设您使用的是 SSR,上述解决方案允许您纯粹 client-side。