CAPTCHA機能を用いたWebフォーム入力を実装する3つのユーティリティ

 現在多くのWebフォームでは、個々のユーザが行うべき登録手続きをコンピュータによって自動処理されるのを防止する機構として、CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart:コンピュータと人間を区別する完全に自動化された公開チューリングテスト)と呼ばれるシステムが利用されている。 ここで言うCAPTCHAとは、Webフォームの入力フィールドにインプットさせる文字と数字からなるテキストを意図的に歪ませたりバックグラウンドにノイズを混入させたイメージ(画像)として画面上に表示させることで、人間だけがイメージとして示されたテキストを読み取れるようにしたシステムである。本稿ではPHP WebサイトにCAPTCHA機能を追加する場合を想定し、そうした用途に利用可能な3つのアプリケーションを比較する。

 多くのCAPTCHAツールはイメージ作成をgdで、フォント処理をFreeTypeにて賄っている。FreeTypeおよびgdが各自のPHPインストレーションにてサポートされているかを確認するには、コマンドライン上で「php -i」を実行してPHPのコンパイルに使われた./configure行をチェックすればいい。サポートされている場合は設定オプションが「--with-gd」とされているはずである。gdのサポートについてはPHP本体とは別パッケージとなっている場合もあるが、PHPランタイムにてgdが使用可能となっている場合は、下記に示した「php -i」の出力例にあるようにgdという表示に続いて設定情報の行が出力されるはずである。

$ php -i
...
gd

GD Support => enabled
GD Version => bundled (2.0.34 compatible)
FreeType Support => enabled
FreeType Linkage => with freetype
FreeType Version => 2.3.5
...

 本稿で取り上げる3つのプログラムの1つであるcapictchaの場合、Fedora 8にて動作させるにあたってはphp-gdパッケージのインストールとApacheのリスタートが必要であった。なおcapictcha-0.3.phpに「error_reporting(E_ALL);」を設定しておくと、PHPからgdにアクセスできない場合は/var/log/httpd/error_logファイルにて下記に示したようなエラーが報告されるようになる。その場合はPHPでサポートさせるgdないしFreeTypeをインストールしなければならない。

PHP Fatal error:  Call to undefined function imagettfbbox()

capictcha

capictcha.png
capictcha

 ここで検証する3つの選択肢のうちで最初に取り上げる capictcha は、指定した文字列のCAPTCHAイメージ作成を行うツールである。このツールはCAPTCHAイメージを作成して返す機能だけに特化しており、PHPクラスを介したアクセスや調整にまで対処した統合フレームワークを意図した作りにはなっていない。こうした仕様のツールが適しているのは、ユーザセッション追跡用のカスタム機能が既に装備済みのPHP Webサイトにて、既存の挙動を変更させることなくCAPTCHA機能を追加させたい場合であろう。

 capictchaの現行版(バージョン0.3)を使用するにはApacheとPHPとgdが必要となる。PHP側からgdにアクセスできなかった場合、ブラウザによるcapictcha.phpの読み込み結果として何も表示されないはずである。

 capictchaのtarボールを展開する先は、各自のApacheにおけるDocumentRootディレクトリとしておく(通常は/var/www/html)。そこに含まれるcapictcha-0.3.phpという名称のPHPファイルを、POSTまたはGETにて必要なCGIパラメータを指定した上で呼び出すと、該当するCAPTCHAイメージが生成されるはずである。

 capictchaに渡すメインのパラメータは、イメージ化するテキスト文字列を指定するtext、イメージの高さを指定するheight、出力させるイメージフォーマット(PNGまたはJPEG)を指定するoutputの3つである。

 CAPTCHAを介したテキストフィールド入力をユーザに強制させたい場合に問題となるのは、Webクライアントへの呼び出し情報をユーザの目から秘匿させて、capictcha呼び出し時に渡すtextパラメータを機械的に直接Webフォームに入力するといった処理をいかにして防止するかである。そのために用意されているのがspecialという第4のCGIパラメータであり、これを用いると具体的なCAPTCHA用文字列をWebクライアント側に公開することなく、事前定義しておいたテキスト文字列を指定するといった操作が可能となる。この機構は、CAPTCHA上に表示させるテキストと対になる選択肢文字列とをマッピングしたルックアップテーブルをcapictchaのPHPファイル中に格納しておくことで機能する。選択肢となる文字列はクライアントの目に曝されるかもしれないが、その対応するテキスト文字列、つまりはCAPTCHAイメージとする文字列は秘匿されるのである。実際にspecialを使用するにはcapictchaのPHPファイルを編集する必要があり、それには「// set up specials」とされた行を特定してCAPTCHA用テキストのリストを登録しておけばいい。

 例えば下記に抜粋したデフォルトのリストをそのまま利用する場合、special=helloというCGIパラメータの指定でcapictchaを呼び出すとHi there!というCAPTCHAテキストが返される。

...
// set up specials
$special_hash = array(
        'punk' => "'" . '"/,.!@#$%^&*()_-=\|+ ',
        'hello' => 'Hi there!',
        'person' => 'SSGTAC',
        'random' => '12345789abdefghijmnqrtuyABCDEFGHIJKLMNOPQRSTUVWXYZ',
);

Captcha PHP

captchaphp.png
Captcha PHP

  Captcha PHP の場合は単にCAPTCHAイメージを生成するだけでなく、CAPTCHA入力用のAJAXフォーム要素の作成およびユーザ入力の判定を行うためのPHP関数APIも装備されている。仮にこのAPIが提供されていない場合、CAPTCHAに表示させるテキスト文字列の生成とユーザが正しい値を入力したかの確認はそれぞれ別途に処理させなくてはならないため、こうしたWebフォームへのCAPTCHA表示機能の追加およびユーザ入力の判定が一括で処理できる点は高く評価すべきだろう。なおCaptcha PHPのAPIを使用するには、PHPスクリプトの先頭部に「include("captcha.php");」という指定を追加しておく必要がある。

 今回私が試用したのはCaptcha PHPのバージョン2.0である。そのインストールについては先のcapictchaと同様、ApacheのDocumentRootにてtarボールを展開しておけばいい。

 Captcha PHPによるフォーム要素の生成は、HTML FORM要素の内部での「print captcha::form();」呼び出しによって該当するAJAXコードが出力されることで行われるが、ユーザが正しい値を入力したかの確認については、サブミットされたフォームの呼び出すPHPスクリプトから「if( captcha::solved() ) { ...ok... }」を実行させる必要がある。

 captcha::form()関数には、CAPTCHAイメージとCAPTCHA入力フィールドの間に配置させるHTMLを指定するためのオプションパラメータも用意されており、例えば下記のコードでは、CAPTCHAの表示イメージとユーザによるCAPTCHA文字列の入力ボックスフォームの間に登録ボタンを表示させている。

captcha::form("<small><a href="...">register</a> to avoid this check</small><br/>");

 ここで生成されるフォームについてはその他にもCSS編集を介したカスタマイズを施すことが可能で、その際に主として手を加えるのは.captchaクラスおよび#captcha IDセレクタである。詳細についてはCaptcha PHPに付属するREADMEファイルを参照して頂きたい。

KCAPTCHA

kcaptcha.png
KCAPTCHA

 既存サイトへの統合の容易さという観点から見た場合、capictchaとCaptcha PHPの間に位置しているのが KCAPTCHA である。KCAPTCHAにも、正しいCAPTCHA文字列をユーザが入力したかを確認するための機能は用意されているものの、このチェック機能はCaptcha PHPのPHP用APIのような扱いやすい形では提供されていない。つまりKCAPTCHAはフォーム中に設けるCAPTCHAイメージと入力フォームを1つのセクションとして丸ごと生成してくれる訳ではなく、その辺の処理は自分で対処する必要がある。

 今回私が試用したのはKCAPTCHAのバージョン1.2.5である。ただしこのtarボールをダウンロードするには電子メールによる確認を伴うphpclasses.orgへの登録が必要となるが、そうした手続きを煩わしいと感じる場合は、先に紹介したいずれかのソリューションを利用すべきかもしれない。なおtarボールの展開はカレントディレクトリにて実行されるので、あらかじめDocumentRootの下層にkcaptchaという名称のサブディレクトリを新規に作成しておき、そこにtarボールを移動しておく方がいいだろう。

 このユーティリティはindex.phpファイルにてCAPTCHAイメージを生成する仕様になっており、example.php.はそのサンプルファイルである。また本パッケージによるCAPTCHAの生成と検証はPHPセッションにて行われ、KCAPTCHAを使用する上でPHPファイルにinclude()を記述しておく必要はない。この方式のデメリットは、下記に示したサンプルのように、ユーザが正しいCAPTCHA入力を行っているかを_SESSIONにて直接テストする検証用コードを自前で用意しなければならない点である。

<form ...>
...
<img src="index.php?<?php echo session_name()?>=<?php echo session_id()?>"><
...
</form>

...

if(isset($_SESSION['captcha_keystring'])
  && $_SESSION['captcha_keystring'] ==  $_POST['keystring'])
{
 ... ok ...
}

自分はどのツールを使用すべきか

 CAPTCHAの本質は、コンピュータによるテキスト読み取りを意図的に困難にしたイメージとしてテキスト文字列を提示することにある。ただし実際の利用者の中には、本稿で紹介したツールで生成されるCAPTCHAイメージの外観や人間の目で見た視認性の高さを優先して、各自のWebサイトにツールを統合する際の親和性は二の次と考える人間もいるだろう。

 プログラミング的な観点から見た場合、CAPTCHAイメージに用いるテキストを明示的に指定したければcapictchaを利用するのが一番手軽なソリューションのはずだ。あるいはWebフォームへのCAPTCHA機能の追加を最優先とするのであればCaptcha PHPこそが最も簡単なソリューションであり、特にこのツールはCSSとの親和性も高くユーザに入力のフィードバックも行えるという余禄まで付いてくる。最後に残されたKCAPTCHAも、Captcha PHPほどではないがWebフォームと簡単に統合可能なCAPTCHAソリューションを目指した作りとなっている。これらの中で私が選ぶとすれば、JavaScriptによるユーザへのフィードバック機能およびCAPTCHA入力が正しく行われたかの検証を行う高度なPHPインタフェースが装備され、無登録で自由にダウンロードできるCaptcha PHPを選択することになるだろう。

Ben Martinは10年以上にわたってファイルシステムに取り組んでおり、博士課程の取得後、現在はlibferris、ファイルシステム、検索ソリューションを中心としたコンサルティング業に従事している。

Linux.com 原文