コンタクトフォームにreCAPTCHA v3を導入した。

コンタクトフォームからのスパムメールが2日に10通くらいのペースで来ていて、困るほどの数でもないけどどうにかしたいレベルにはなってきたので、reCAPTCHA v3を導入してみました。

「私はロボットではありません」選ぶ必要なし 新「reCAPTCHA」Googleが公開、ユーザーは何もしなくてOK - ITmedia NEWS
reCAPTCHA v3  |  reCAPTCHA  |  Google Developers

Akismetでもよかったのですが、今までコメントフォームに使ってみて誤検知が結構多い印象だったのと、公開されたばかりなので試してみたいこともあり、こっちにしてみました。
判定の流れとしては以下のとおりです。

  1. クライアントサイドでtokenを取得
  2. 取得したtokenを元にサーバサイドでverify用のAPIを呼び出す
  3. APIから返ってきた結果をもとに、ページにアクセスしてきたのが人間かロボットかを判定する

クライアントサイドの導入方法

  1. 管理ページでAPI実行用のキーを発行する。
  2. 管理ページにjsロード用のscriptタグのスニペットが表示されるので、reCAPTCHAしたいページのhead内に埋め込む。
  3. 管理ページにreCAPTCHAのexecute用のscriptタグのスニペットが表示されるので、reCAPTCHAしたいページのどこかしらに埋め込む
<script>
grecaptcha.ready(function() {
  grecaptcha.execute('Site key', {action: 'action_name'}) // action_nameはサーバサイドの処理で使用する
    .then(function(token) {
    // Verify the token on the server.
  });
});
</script>

サーバサイドの導入方法

  1. クライアントからtokenを受け取る。
  2. Secret keyとtokenを使用してスコアの問い合わせを行う。APIからのレスポンスの形式はドキュメントを参照
curl https://www.google.com/recaptcha/api/siteverify  -X POST -d "secret=secret&response=token"
{
  "success": true,
  "score": 0.9,
  "action": "contact_form", // クライアントサイドで決めたaction_name
...
}

しきい値を決めて、それを下回るならエラーを返す等の処理をサーバサイドに書きます。

コンタクトフォームはContact Form 7を使用しているのですが、そのうちプラグイン側がv3に対応しそうなのと、自分で改造するのが面倒なので、reCAPTCHA用のエンドポイントを設置して、「エンドポイントからのレスポンスが200以外だったら、送信ボタンのDOMをremoveした上でsubmitイベントを無効化する」とかいう意味があるんだかないんだかわからない処理を入れておきました。
DOMの処理終わる前に送信されたら意味ないし、そもそもスパムの送信元がJS無効化してたら詰むんだけどまぁものは試しなので…。
reCAPTCHA用のjsも本当は全ページに読み込ませないといけないのですが、スパムの送信元はどうせコンタクトフォームに直接アクセスしてきてるので、コンタクトフォームのページにだけ読み込ませています。

設置してから4日くらい経ちますが、スパムが3通くらいしか届いていないのである程度効果はあるのかなと思っています。

だから私はQiitaに投稿しない。

最近のQiitaの記事の質が下がってきている事への考察 – Qiita
これ読んでいろいろ思うことがあったのでポエム。

メールで問い合わせ受けたときに何回か「この記事Qiitaに投稿してほしかった(Qiitaに投稿してくれたらもっと早く見つけられた)」と言われたことがあるんですが、私は多分Qiitaには行かないと思います。

ポエムとかJAVAの人の記事は論外として、何かしら記事書いても「質の高い記事を投稿しろ」って言われてしまうなら、じゃあQiitaには投稿しないわ、ってなっちゃう。
今までQiitaに投稿された色々な記事に助けられてきたけど、私の書く記事がそうなれるかって言ったらなれないんですよね。多分。

Qiitaって技術ブログのInstagramみたいだとずっと感じてて、見る分にはほんとに楽しいしすごいなぁって思うんですが、私は投稿するのきついです。
意識高い人やいけてる人がめっちゃキラキラした写真を投稿するように、いけてるベンチャーの人やバリバリのフリーランスの人やレベルの高いエンジニアがレベルの高い記事を投稿するのがQiitaで、Qiitaには質の高いものばっかりなきゃいけない、みたいな感じになってる気がします。(でもそれってほんとにQiitaと、Qiitaを見に来る人にとっていいことなんですかね?)
「質の高い記事だけ探して読むわ」って人が集まるんじゃなくて「質の高い記事だけ投稿しろ」っていう人が集まってるところに記事投稿しても自分が悲しくなるだけだなぁって。

ポエムも書きたいし自分の好きな言語だけで好きなものだけ作りたいので、私はこのブログでいいです。

Gutenberg 4.1.1が有効の状態でSyntaxHighlighter Evolvedを使うとbr /が混ざる。

「新しいものは良いもの」という信条があるのでOSアップデートでもなんでも即試すんですが、ただしGutenberg、テメーはだめだ。
Gutenberg | WordPress.org
レビューにdisasterってコメントがあるのは笑ってしまった。

もう絶対原因こいつだろと決めてかかって無効化したらSyntaxHighlighter Evolvedで出力してる箇所にbr /は混ざらなくなりました。これ標準エディタ化されるとマジで詰みますね。どうしよう。
原因まで調べてる時間がなかったので、具体的にどのコードがSyntaxHighlighter Evolvedにちょっかいをかけているのかはわかっていないです。とりあえずメモとして記事を残しておきます。

某飲食店予約システムのインフラ構成を予想したい。

インフラのイの字もわからないのにインフラ系のことをせざるを得ない状況になっており、勉強のために某飲食店予約システムのインフラ構成を予想しようと思いました。ピンクくて丸いやつ向けです。

注意

記事の内容は、野球の試合をテレビで見ながらイチャモンをつけるおっさんくらい薄く、知識量に比例して正確性は皆無です。インフラをわかってない人が頑張るとこういう予想にたどり着くんだね、という参考にはなるかもしれません。

参考にしたページ

とりあえず情報を集めます。

トレタのインフラ運用、支えている道具(Packer, Terraform, Serverspec, Ansible, Roadworker, Circle CI)、考え方 – トレタ開発者ブログ
トレタのインフラ運用 – Speaker Deck
トレタのMySQL MySQL casual #8
記事が結構古いからだいぶ変わってそうですね。どっかに答え載ってるんじゃないかと思って開発者ブログを見てみたけど最近の記事はなかった…。SlideShareとかにはあるのかもしれないですね。

うっす~いよそう

実際に使ってみてのエラーの返り方やレスポンスの感じだと以下のような構成でしょうか…?

  • サーバ:Amazon EC2
  • ロードバランサ:ALB?NLB?
  • バックエンド:Ruby on Rails
  • DB:Amazon RDS for MySQL
  • 静的コンテンツ(json等):CloudFront
  • 静的コンテンツ(画像等):Amazon S3

default backend – 404(多分Nginx Ingress Controllerのデフォルトバックエンドのレスポンス)が時たま返ってきたことから予想すると、おそらくRoRはKubernetesのPodで動いてるかもしれません。AWSを使ってるなら、GKEを採用しているのかなぁと予想しました。(リバースプロキシもIngressを使用)

実際の挙動からのうっす~いよそう

予約用の内部APIは予約対象の店舗のIDごとに処理する仮想サーバが決まっているわけではないようで、一店舗に予約処理が集中すると他の店舗のリクエストも応答しなくなるという挙動でした。(実際、先月はそれで巻き添え食らったところが落ちていた)
EC2使ってるならスケールアウトするか、予行演習で前もってやばいのはわかってたので、ピンクいやつだけL7ロードバランサでRDSもRoRも専用のインスタンスに処理させるとかいくらでも手は打てたと思うのですが、どうしてこうしなかったのかはよくわかりません。

以下を読んだのですが、ELB自体は5万RPSかけても受けきれるっぽいのと、API叩いたときに502 Bad Gateway返ってきてたので、Ingress Controllerまでは問題なくて、バックがボトルネックになっているのかなぁと思いました。(小学生並みの感想)
[社内勉強会]ELBとALBと数万スパイク負荷テスト

感想

やっぱりよくわからない。

Metabaseを使ってポケモンGOで孵化したタマゴの情報を可視化する。

旦那さんとポケモンGOをプレイしているのですが、タマゴから孵るポケモンに偏りがあるかを知りたかったので、記録を取るようにしています。
記録の方法は以下の通り。

  1. タマゴが孵化したらLINEグループ宛に報告する
  2. 報告をLINE botが拾ってDB(SQLite3)に書き込む

LINE botと会話して統計を取れるようにはなっているのですが、テキストベースだと情報がデジタルでいまいちピンとこないため、Metabaseで情報を可視化してみることにしました。最初Grafanaが使いたかったのですが、SQLiteに対応していないので自動的にMetabase一択になりました。

動かし方

インストールは以下の記事を参考にしました。
OSSのデータ可視化ツール「Metabase」が超使いやすい
Dockerが多分一番楽に立ち上げられる気がします。私の環境はいろいろあってDockerが動かせないので、jarをそのままOpenJDK 8で動かす方法をとりました。使用したMetabaseのバージョンは0.30.1です。デフォルトだと3000番がMetabaseのポートになります。
セットアップはほんとに楽すぎて何も困ることなかったので割愛。

可視化したいDBの設定

DBの追加画面

ここから解析対象のDBまでのパスを入力すればすぐ解析してくれます。

DBの可視化結果とか

DBの可視化結果
ポケモンの円グラフとかホエルコのグラフとか

お互いが孵したポケモンの円グラフを作ってみました。本当はグラフの横に凡例と値が出力できるのですが、GUIのバグで凡例が多すぎるとグラフが表示できなくなるため、非表示にしています。カーソルを当てると内容がわかるのですが、不便なので次バージョンに期待します。

DBのフィルタリング結果

フィルター機能で期間やタマゴの距離を絞り込むこともできます。めちゃくちゃ楽です。

使ってみた感想

私がQuestionをあまり上手に使いこなせていないので、今の所Kibanaのように息を吸って吐くレベルのグラフ作成には到達できていません。が、最悪SQL文を書いてもグラフは作れるので、可視化するには困らなさそうです。ただ動かすまでの手軽さは、ElasticSearchとFluentdのハードルが高い分、圧倒的にMetabaseのほうが勝ります。java jarコマンド打つだけだったので本当に手軽でした。アクセスログを解析するぐらいであれば、Metabaseで十分用が足りると思います。GUI周りのバグについては今後の修正に期待したいと思います。

あと、旦那さんが使っているブラウザがモダンブラウザではないので、表示がバグったり動作しないスクリプトがあったりするのが悩みどころです。他人とダッシュボードを共有するときは、モダンブラウザの使用ルール化することをおすすめします。