コメントスパム対策・実践編
ちょっと時間が空きましたが、先日のコメントスパム対策・理論編 - @ikikko のはてなダイアリーで取り上げたCAPTCHAの設定です。実はCAPTCHAの設置だけならば大した手間ではなかったのですが、それに伴っていくつか懸念事項が発生したので、その分の付加作業にも対処してました。
CAPTCHAの設置
まずはPerl上でCAPTCHA画像の生成。Authen::Captchaのモジュールを使わせてもらいます。
# CAPTCHAオブジェクト生成 my $captcha = Authen::Captcha->new( data_folder => $captcha_data, output_folder => $captcha_output, ); # 6文字の画像生成 my $md5sum = $captcha->generate_code(6);
続いては、上記で生成した画像と、画像からユーザが推測した文字を入力するフィールドの表示。当たり前ですが、どの画像を表示しているかの情報をhiddenパラメータででも渡してやらないと、ユーザが推定した入力が正しいのかが後続処理で判断できません*1。
<img src="$captcha_output/$md5sum.png" /> <form method="POST" action="./captcha.cgi"> <input type=text name="captcha" value="画像内の文字列を入力してください"> <input type=hidden name="md5sum" value="$md5sum"> <input type=submit> </form>
あとは、CGIの遷移先で画像の表示値とユーザの入力値をつき合わせてやります。
# CAPTCHAオブジェクト生成 my $captcha = Authen::Captcha->new( data_folder => $captcha_data, output_folder => $captcha_output, ); # ユーザ入力値のチェック my $result = $captcha->check_code($FORM{'captcha'}, $FORM{'md5sum'}) # 違っていた場合、エラールーチンに遷移 &error("画像の文字列と入力された文字列が違います") unless $result = 1;
登録画面への入力フォーム値戻し
と、↑までが実際のCAPTCHAの作業ですが、ここで問題点が発生しました。正常にユーザが推測できた場合はいいのですが、間違った場合のルーチンが既存のやつそのままだとちょっと困ったことになったのです。
現状だと登録画面で何かエラーが起こった場合、ただエラーの内容(例:「名前が入力されていません」)を出力するだけになっていました。ここで、ブラウザの「戻る」ボタンで戻ると入力した内容はそのままですが、CAPTCHA画像もそのままになってしまいます。一度推測失敗したCAPTCHA画像は消去される*2ので、このまま何度リトライしても失敗するだけになってしまいます。かといって、更新をかけてやるとせっかくフォームに入力した値が消えてしまいます*3。
ちょっと考えた結果、エラー画面に登録画面へ戻る用のボタンを作って、そこから戻ってもらうようにしました。エラー画面には、登録時のフォーム値が入ってくるはずなので、それをそのままhiddenパラメータで戻してやれば大丈夫でしょう。ま、Webアプリケーションによくある処理ですね。
コメントスパム対策にとって本質的ではないので、実際のコードは省略。