我正在使用 nuxt 并且想使用这个库:https://github.com/nuxt-community/recaptcha-module。但我不明白如何验证用户是否通过了检查。这个例子并没有告诉我太多(https://github.com/nuxt-community/recaptcha-module/blob/master/example/v3/pages/index.vue)。有人可以告诉我如何正确地做吗?
这个例子只是故事的一半。它在客户端返回 Recaptcha V3 令牌。
然后必须将其发送到服务器端并使用您的密钥进行验证。
这是通过向此 URL 发送帖子来完成的:
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${token}`;
您不想在客户端允许此密钥。
要在 Nuxt 中实现此目的,假设版本为 2.13+,您可以在 nuxt 配置中使用
privateRuntimeConfig
。
这将允许您链接仅在服务器端注入的 .env 文件。
对于这个用例,像这样的 privateRuntimeConfig 应该足够了:
privateRuntimeConfig: {
secretKey: process.env.GOOGLE_SECRET
}
完成此操作后,您将能够在 Nuxt 应用程序中作为
this.$config
的一部分访问这些变量 - 在本例中为 this.$config.secretKey
当调用 Recaptcha 验证端点时。
了解更多信息查看 Nuxt 博客
在您的 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
},
请记住,
modules
,这与buildModules
不相同(有时可能会因相似的命名而造成混淆)。
这是 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' },
],
中间件/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
注意它所说的部分
服务器端 当您向服务器发送数据+令牌时,您应该在服务器端验证令牌以确保它不是从机器人请求的。您可以通过查看 v2 示例中的服务器中间件来了解如何在服务器端验证令牌。 (两个版本的服务器端相同)
上面的服务器端中间件就来自那里。使用我建议的
h3
版本非常重要,因为您需要它来访问 useBody(req)
。我尝试了几个小时来寻找另一种读取请求正文的方法,但事实证明这太困难了。在较新版本的 Nuxt 中,您的结果可能会有所不同。我建议尝试最新版本的 h3
,如果在构建应用程序时失败并出现错误,请尝试旧版本。
不要暴露 ReCaptcha 密钥至关重要,该解决方案在服务器端对其保密。
更佳的解决方案可能是使用您的实际服务器并创建一个端点来验证 ReCaptcha 令牌。假设您使用的是 SSR,上述解决方案允许您纯粹在客户端执行此操作。