带有 vue-recaptcha-v3 (v1.8.0) 的 reCAPTCHA v3 不断通过提取验证失败 API
reCAPTCHA v3 with vue-recaptcha-v3 (v1.8.0) constantly failing verification with the fetch API
在我的带有节点模块 vue-recaptcha-v3
的 VueJS 应用程序中,reCAPTCHA v3 在验证步骤 中不断失败。 "protected by reCAPTCHA" 横幅按应有的方式出现在页面上,我在验证步骤之前得到的响应很好。当我尝试通过 fetch
:
POST
将令牌 https://www.google.com/recaptcha/api/siteverify
// Execute reCAPTCHA with action "login".
const response = await this.$recaptcha('contact');
const data = {
secret: secretKey,
response,
};
try {
const validationResponse = await fetch(validationUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
[...]
我只是得到错误 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.google.com/recaptcha/api/siteverify. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
所以我用mode: 'no-cors'
代替:
[...]
const validationResponse = await fetch(validationUrl, {
method: 'POST',
mode: 'no-cors',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
[...]
然后导致此响应:
{
"success": false,
"error-codes": [
"missing-input-response",
"missing-input-secret"
]
}
我想你不能在 no-cors
模式 (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options) 中发送 json 的内容类型,所以我改用 multipart/form-data
作为内容类型:
const response = await this.$recaptcha('contact');
const formData = new FormData();
formData.append('secret', secret_key);
formData.append('response', response);
try {
const validationResponse = await fetch(validationUrl, {
method: 'POST',
mode: 'no-cors',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData,
});
[...]
但这只会导致 Google 的回应:
<HTML>
<HEAD>
<TITLE>Bad Request</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Bad Request</H1>
<H2>Error 400</H2>
</BODY>
</HTML>
我真的不知道该怎么办了——我错过了什么?
好的,我终于在 Whosebug 找到了答案: - 长话短说:Googles reCAPTCHA 验证服务器似乎只接受 "Content-Type": "application/x-www-form-urlencoded"
,所以发送的数据我的情况需要
body: 'secret=' + secretKey + '&response=' + response
。
使用这些设置不会发生错误(请注意:像这样发送的数据需要通过 URLencode 进行清理!我在这个例子中忽略了它。)
但它仍然令人困惑,例如Firefox 显示来自 Google 的正确响应,但 Vue 应用程序根本无法读取它 - response.ok euqals false!
原因:browser/client本身无法处理no-cors
响应。服务器必须这样做!因此必须将 reCAPTCHA 响应发送到您的服务器,并且服务器(例如 PHP)必须将数据发送到 Google 的验证脚本。没有其他办法解决这个问题。 Google reCAPTCHA 的文档遗漏了所有这些要点。
此外 - 令我感到羞耻的是我现在才意识到这一点 - 这完全有道理,因为对于 reCAPTCHA 验证,你需要你的 secret reCAPTCHA 密钥,而那个密钥绝对不应该存储在发送给客户端的 JS 应用程序中。你永远不会泄露你的秘密。
在我的带有节点模块 vue-recaptcha-v3
的 VueJS 应用程序中,reCAPTCHA v3 在验证步骤 中不断失败。 "protected by reCAPTCHA" 横幅按应有的方式出现在页面上,我在验证步骤之前得到的响应很好。当我尝试通过 fetch
:
POST
将令牌 https://www.google.com/recaptcha/api/siteverify
// Execute reCAPTCHA with action "login".
const response = await this.$recaptcha('contact');
const data = {
secret: secretKey,
response,
};
try {
const validationResponse = await fetch(validationUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
[...]
我只是得到错误 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.google.com/recaptcha/api/siteverify. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
所以我用mode: 'no-cors'
代替:
[...]
const validationResponse = await fetch(validationUrl, {
method: 'POST',
mode: 'no-cors',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
[...]
然后导致此响应:
{
"success": false,
"error-codes": [
"missing-input-response",
"missing-input-secret"
]
}
我想你不能在 no-cors
模式 (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options) 中发送 json 的内容类型,所以我改用 multipart/form-data
作为内容类型:
const response = await this.$recaptcha('contact');
const formData = new FormData();
formData.append('secret', secret_key);
formData.append('response', response);
try {
const validationResponse = await fetch(validationUrl, {
method: 'POST',
mode: 'no-cors',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData,
});
[...]
但这只会导致 Google 的回应:
<HTML>
<HEAD>
<TITLE>Bad Request</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Bad Request</H1>
<H2>Error 400</H2>
</BODY>
</HTML>
我真的不知道该怎么办了——我错过了什么?
好的,我终于在 Whosebug 找到了答案:"Content-Type": "application/x-www-form-urlencoded"
,所以发送的数据我的情况需要
body: 'secret=' + secretKey + '&response=' + response
。
使用这些设置不会发生错误(请注意:像这样发送的数据需要通过 URLencode 进行清理!我在这个例子中忽略了它。) 但它仍然令人困惑,例如Firefox 显示来自 Google 的正确响应,但 Vue 应用程序根本无法读取它 - response.ok euqals false!
原因:browser/client本身无法处理no-cors
响应。服务器必须这样做!因此必须将 reCAPTCHA 响应发送到您的服务器,并且服务器(例如 PHP)必须将数据发送到 Google 的验证脚本。没有其他办法解决这个问题。 Google reCAPTCHA 的文档遗漏了所有这些要点。
此外 - 令我感到羞耻的是我现在才意识到这一点 - 这完全有道理,因为对于 reCAPTCHA 验证,你需要你的 secret reCAPTCHA 密钥,而那个密钥绝对不应该存储在发送给客户端的 JS 应用程序中。你永远不会泄露你的秘密。