=encoding utf8 =head1 NAME WebService::CaptchasDotNet - 無料のCAPTCHAサービスcaptchas.net用のルーチン =head1 SYNOPSIS # オブジェクトの生成 my $o = WebService::CaptchasDotNet->new(secret => 'secret', username => 'demo'); # この画像URLのためのランダム文字列の生成 # $o->random()を_必ず_使用し、自分でランダム文字列を # 与えることはできないことに注意 my $random = $o->random; # 画像URLの生成 my $url = $o->url($random); # 入力されたcaptchaと画像がマッチしているか判定 my $ok = $o->verify($user_input, $random); =head1 DESCRIPTION WebService::CaptchasDotNetには http://captchas.net の無料のCAPTHCAサービスを利用するための、いくつかの便利なルーチンがあります。 これらのルーチンを使用するには、 http://captchas.net を訪れて、そこで登録する必要があります。そこで、これらのルーチンを動かすのに必要な、ユーザ名(username)と共有秘密鍵(shared secret key)が提供されます。 =head1 CONSTRUCTOR =over 4 =item new() 新しいWebService::CaptchasDotNetオブジェクトのインスタンス化を行います。 my $o = WebService::CaptchasDotNet->new(secret => 'secret', username => 'demo', expire => 1800); 引数は下記になります。 =over 4 =item secret captchas.net サービスに登録した際に与えられた秘密鍵です。この引数は必須です。 =item username captchas.net サービスに登録した際に与えられたユーザ名です。この引数は必須です。 =item expire キャッシュされたランダム文字列が無効になるまでの時間を秒で指定します。詳細は後述のrandom()のドキュメントを参照してください。この引数はオプションで、デフォルトは3600秒です。 =back 必須の引数が与えられなかったとしても、それでも妥当なオブジェクトが返されますが、しかしverify()は常に失敗します。 mod_perlなどの永続化(persistent)環境でオーバヘッドを最小限にしたければ、パッケージレベルで単一のオブジェクトを構築し、これを以降のプロセスのために保持することができます。 =back =head1 METHODS =over 4 =item verify() 判定のルーチンで、これがインターフェースの心臓です。基本的には、これはユーザが入力したCAPTCHAフレーズを受け取り、これがcaptchas.netから与えられた画像にマッチするかをチェックします。 my $ok = $o->verify($user_input, $random); この'$user_input'はユーザーがキー入力したもの、'$random'はあなたがcaptchas.net URLに付け加えたランダム文字列です。例えば、Webページに表示されたURLが http://image.captchas.net?client=demo&random=RandomZufall であれば、呼出し方は次のようになります。 my $ok = $o->verify($user_input, 'RandomZufall'); したがって、基本的には、ランダム文字列のトラックを、呼出し間でなんらかのステートフルな作法に従って、自分で保持しておく必要があります。個人的には、私はhiddenフィールドを使用していますが、しかしあなたにはあなたのやり方がある(YMMV)でしょう。 verify()とrandom()メソッドは緊密に関係したものだということを心に留めて置いてください - verify()にはrandom()メソッドで生成したランダム文字列を渡さなければならず、単にランダムな何らかのランダム文字列を使うということはできません。詳細は後述のrandom()のドキュメントを参照してください。 verify()はユーザがCAPTCHA画像の文字列を正しく認識していればtrueを、それ以外の時にはfalseを返します。 =item random() random()はランダム文字列を生成するためのユーティリティーメソッドです。 my $random = $o->random; random()とverify()メソッドは関連しており、random()で生成されたランダム文字列だけが、verify()にtrueを返させます。以下がその理由です... ハッカーであろうという人がCAPTCHA画像と、完全にランダムな文字列で補完された記録された画像URLを表示されていると想像します。 ハッカーはプログラム的に同じくランダム文字列を使用し、次の要求を送るふりをして、あなたのシステムを汚すことができるでしょう。 それゆえに、ランダム文字列は一度はあなたによって確認され、そして一度だけ、もう一方の端に人間がいることを確かめる必要があります。 本当のパラノイドにとっては、ランダム文字列は生成されてから所定の限られた時間内に受け取られるべきものでしょう。 random()とverify()の結合は、これらの両方の必要性を満たします。 random()が呼出されると、ランダム文字列がファイルシステム上のキャッシュに保持されます。 verify()はファイルがあるか、そして新鮮さを失っていないかを確認し、ユーザの入力が良ければ、これを削除します。 captchas.netのアルゴリズムにユーザの入力がパスしたかによらず、ファイルが存在し最近のものの場合にのみ、verify()は成功します。 ユーザの入力が悪い(本当にミスタイプのレスポンスのような)のであれば、ファイルはファイルシステム上に残されますので、ユーザは完全にページをリフレッシュすることなく、もう一度試すことができます。 これは、ファイルが新鮮ではなくなったとみなされるまでずっとです。 random()のキャッシュは、デフォルトでは$TMPDIR/CaptchasDotNet/にあります。 $TMPDIRがどこであるかというのは、File::Spec->tmpdir()を介して決められます。 このrandom()の実装に関する警告として、これはファイルシステムベースであるため、共通のマウントポイントを持たないクラスタ環境にあるならば、ランダム文字列を供給するボックスが、後で判定に用いられるものにはならない可能性が強く、筋の通ったマッチングに対して失敗を起こします。 この場合、WebService::CaptchasDotNetのサブクラスを作成し、_init()を上書きして、キャッシュファイルのための異なるパスを選択しようとすべきです。 =item url() Webページに埋め込むための、captchas.netに適したURLを生成します。 my $url = $o->url($random); 返されたURLは渡されたランダム文字列と、コンストラクタで与えられたユーザ名の両方を、埋め込まれた形で持ちます。 例えば my $o = WebService::CaptchasDotNet->new(secret => 'secret', username => 'demo'); my $random = 'RandomZufall'; # http://image.captchas.net?client=demo&random=RandomZufall my $url = $o->url($random); 返されたURLがWebページ上での表示に適切なようにエンコードされていることは重要な点で、アンパサンと(&)自体もエンコードされていることを意味します。これは間違いなく、あなたの生成されたページが妥当なxhtmlのままにします :) =item expire() キャッシュのランダム文字列が期限切れになるまでの時間(秒数)をセットします。 $o->expire(1800); 期限切れ時間のデフォルトは3600秒で、これはユーザに60分の妥当性確認の時間を与えます。 =back =head1 DEBUGGING もし何かあなたが計画した通りにいかなくて、冗長なエラーメッセージに興味があれば、以下のようにしてデバッギングを有効にできます: use WebService::CaptchasDotNet; $WebService::CaptchasDotNet::DEBUG = 1; =head1 SEE ALSO http://captchas.net/ =head1 AUTHOR Geoffrey Young =head1 COPYRIGHT Copyright (c) 2005, Geoffrey Young All rights reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself. =head1 DOCUMENT TRANSLATION Makio Tsukamoto, tsukamoto@gmail.com =cut