reCAPTCHA v3 с vue -recaptcha-v3 (v1.8.0) постоянно не проходит проверку с помощью API выборки - PullRequest
0 голосов
/ 16 марта 2020

В моем приложении VueJS с модулем узла vue-recaptcha-v3, reCAPTCHA v3 постоянно завершается ошибкой на этапе проверки . Баннер «Защищено reCAPTCHA» появляется на странице, как и должно быть, и ответ, который я получаю перед этапом проверки, в порядке. Когда я пытаюсь POST токен https://www.google.com/recaptcha/api/siteverify через fetch:

// 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"
  ]
}

Я полагаю, вы не можете отправить тип контента json в режиме no-cors (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options), поэтому вместо этого я использую 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>

Я действительно не не знаю, что делать дальше - чего мне не хватает?

1 Ответ

1 голос
/ 16 марта 2020

Хорошо, я наконец-то нашел ответ здесь, в StackOverflow: reCAPTCHA - коды ошибок: «missing-input-response», «missing-input-secret» при проверке ответа пользователя (недостающие данные в POST) - Короче говоря: сервер проверки Googles reCAPTCHA, похоже, принимает только "Content-Type": "application/x-www-form-urlencoded", поэтому данные, отправляемые в моем случае, должны быть

body: 'secret=' + secretKey + '&response=' + response.

С этими настройками ошибка не возникает (обратите внимание: данные, отправленные таким образом, должны быть обработаны v ie URL-код! Я не учел это в этом примере.) Но все же сбивает с толку то, что, например, Firefox показывает правильный ответ от Google, но приложение Vue не может его прочитать вообще - response.ok euqals false!

Причина: Браузер / клиент не может справиться с no-cors ответ сам по себе . Сервер должен сделать это! Поэтому ответ reCAPTCHA должен быть отправлен на ваш сервер, а сервер (например, PHP) должен отправить данные в скрипт проверки Google. Другого пути нет. В документах Google reCAPTCHA пропущены все эти важные моменты.

Кроме того, к своему стыду, я только что понял это сейчас - в этом есть смысл, потому что для проверки reCAPTCHA вам нужен ключ secret reCAPTCHA и это однозначно не должно храниться в вашем JS приложении, которое отправлено клиенту. Вы никогда не раскроете свой секрет.

...