LoginSignup
4

More than 3 years have passed since last update.

私はロボットではありません reCAPTCHA v3設置(Go)

Posted at

スクリーンショット 2019-04-12 16.45.23.png

最近管理しているサーバーに不正なアクセスが多発していて、
お問合せフォームに最終データをPOSTしてきやがるBOTが多い事多い事。

という事で最終チェックにGoogleの提供しているreCAPTCHAを取り入れる事にしました。
v2はチェックつけるタイプでv3はなんと何もせずにスコア値で評価されるとの事です。

設置の流れ
* KeyとSecretを取得
* javascriptを設置してスコアを収集(トークンに隠蔽されます)しフォーム送信
* バックエンドでGoogleのAPIにトークンを問い合わせてスコアを取得

こんな感じです。詳しくは公式ドキュメントに。
PHP版は書いている方がいたので(GoogleのreCAPTCHA v3をPHPで使う
今回はバックエンド部分をGoでさくっとやってみます。

githubに全ソース置きました
キーさえ取ればdocker-composeで即動かせます。

1.KeyとSecretを取得

Googleアカウントが必要です。
https://www.google.com/recaptcha/にアクセスし、Admin Consoleからサイトキー、サイトシークレットを取得します。
スクリーンショット 2019-04-12 16.51.20.png

タイプはv3を。ローカルでテストする場合ドメインには0.0.0.0localhost等を入れる必要があります。

2.フロントにjavascriptとinputフィールドを追加

{{YOUR_SITE_KEY}}は取得したキーを置き換えてください。githubのソースではgoのtemplateを使ってます。

<!-- reCAPTCHA -->
<script src="https://www.google.com/recaptcha/api.js?render={{YOUR_SITE_KEY}}"></script>
<script>
  var recaptcha = document.getElementsByName('recaptcha_token');
  console.log(recaptcha);
  if (recaptcha != null) {
    grecaptcha.ready(function() {
      grecaptcha.execute('{{YOUR_SITE_KEY}}', {action: 'homepage'}).then(function(token) {
        recaptcha[0].value = token
      }, function (reason) {
        console.log(reason)
      });
    });
  }
</script>
<!-- /reCAPTCHA -->

homepageの部分は以下4つから選べる。
* homepage:See a cohesive view of your traffic on the admin console while filtering scrapers.
* login:With low scores, require 2-factor-authentication or email verification to prevent * credential stuffing attacks.
* social:Limit unanswered friend requests from abusive users and send risky comments to moderation.
* e-commerce:Put your real sales ahead of bots and identify risky transactions.

フォーム内にトークン送信用のフィールドを設置

some field... 
<input type="hidden" name="recaptcha_token" value=""/>
... submit button

ここまででアクセスした時点でサイトの右下にシールがつきます。
valueにもすぐにパラメータが入ってきます。

3.バックエンド(Go)

問い合わせ用の関数と結果の受け取り用のstructはこんな感じ。
"YOUR_SITE_SECRET"を取得したシークレットに置き換えてくださいね。


type RecaptchaResponse struct {
    Success     bool      `json:"success"`
    Score       float64   `json:"score"`
    Action      string    `json:"action"`
    ChallengeTS time.Time `json:"challenge_ts"`
    Hostname    string    `json:"hostname"`
    ErrorCodes  []string  `json:"error-codes"`
}

func reCaptchaVerify(token string) (r RecaptchaResponse, err error) {
    const recaptchaServerName = "https://www.google.com/recaptcha/api/siteverify"
    resp, err := http.PostForm(recaptchaServerName,
        url.Values{"secret": {"YOUR_SITE_SECRET"}, "remoteip": {"127.0.0.1"}, "response": {token}})
    if err != nil {
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return
    }
    err = json.Unmarshal(body, &r)
    if err != nil {
        return
    }
    return
}

フォームから送信されたトークンを渡します。

if r, err := reCaptchaVerify(r.FormValue(FormNameRecaptcha)); err == nil {
  if r.Success && r.Score > 0.7 {
      // success action
    } else {
      // error action
    }
  }
}

スコアはユーザーエージェントの付け替えや、広告ブロック等の状態で変動するそうです。
広告ブロックくらいは許して良いだろという事で0.7くらいで丁度いいかなと思いますが
実際に動かして調整してみると良いかもしれません。

スクリーンショット 2019-04-12 16.34.40.png

参考

GoogleのreCAPTCHA v3をPHPで使う

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4