web-dev-qa-db-ja.com

reCAPTCHA-エラーコード:ユーザーの応答を検証するときの「missing-input-response」、「missing-input-secret」(POSTの詳細がない)

Webアプリケーションに invisible reCAPTCHA を設定していて、ユーザーの応答を確認できません。 (正しいPOSTパラメータを渡していますが)

プログラムで、クライアント側でgrecaptcha.execute();を呼び出してチャレンジを呼び出しています。その後、recaptchaコールバックを使用してフォームを送信します(registrationForm.submit();):

<div class="g-recaptcha"
  data-sitekey="SITE_KEY"
  data-callback="onSubmit"
  data-size="invisible">
</div>

"ユーザーの応答の検証" のドキュメントを読んだ後、応答トークンがPOSTパラメータをg-recaptcha-responseに:

Webユーザーの場合、次の3つの方法のいずれかでユーザーの応答トークンを取得できます。

  • ユーザーがサイトでフォームを送信するときのg-recaptcha-response POSTパラメーター
  • ...

したがって、私は Fetch を使用して、サーバー側で 検証エンドポイント へのPOSTリクエストを作成し、必要な本文データを指定します。

verify(req, res, next) {
  const VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";

  return fetch(VERIFY_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      secret:   process.env.RECAP_INVIS_SECRET_KEY,
      response: req.body['g-recaptcha-response'],
    }),
  })
  .then(response => response.json())
  .then(data => {
    res.locals.recaptcha = data;
    return next();
  });
}

しかし、私は次の応答を得続けます:

{成功:false、エラーコード:['missing-input-response'、 'missing-input-secret']}

POSTボディでJSONデータとしてレスポンスとシークレットを渡していますが。

私は何か間違ったことをしていますか?よろしく。

18
U-ways

reCaptcha Google forums を少し調べて掘り下げてみると、このエンドポイントはデフォルトのコンテンツタイプしか受け入れないようです。 application/x-www-form-urlencoded

つまり、JSONを使用して応答トークンとサイトキーを送信することはしない必要があります。代わりに、application/x-www-form-urlencodedの定義方法として値を送信します。

このコンテンツタイプで送信されるフォームは、次のようにエンコードする必要があります。

  1. コントロールの名前と値はエスケープされます。 [RFC1738]のセクション2.2で説明されているように、スペース文字は「+」に置き換えられ、予約文字はエスケープされます。非英数字は、「%HH」、パーセント記号、およびASCIIキャラクターのコード。改行は「CR LF」ペア(つまり、「%0D%0A」)として表されます。
  2. コントロールの名前/値は、ドキュメントに表示される順序でリストされています。名前は値と「=」で区切られ、名前と値のペアは「&」で相互に区切られます。

したがって、URLを介してPOSTパラメータを渡し、それをPOSTリクエストとして送信するという、2つの方法があります。

https://www.google.com/recaptcha/api/siteverify?secret=${SECRET_KEY}&response=${req.body['g-recaptcha-response']}

または手動で次のようにデータを本文に追加します:

verify(req, res, next) {
  const VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";

  return fetch(VERIFY_URL, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: `secret=${SECRET_KEY}&response=${req.body['g-recaptcha-response']}`,
  })
  .then(response => response.json())
  .then(data => {
    res.locals.recaptcha = data;
    return next();
  });
}
8
U-ways