また、紹介やAPIを提供しているサイトはあれど、ソースや実装方法を公開しているところは何故かありません。
というわけで手っ取り早く作ってしまいましょう。
必要なのは沢山の画像。
今回は「みーたんの素材屋」のアイコン素材を使わせて頂きました。
簡単な作成方針としては、OKフォルダとNGフォルダから画像をいくつか選び、OKフォルダの画像であれば正しいと判断するというものです。
ただフォルダ名がOKとかNGのままでは正解がバレバレですので、一旦別のフォルダに移し、ファイル名もランダム化してから表示させることにします。
まずcatフォルダとcat_okフォルダ、cat_ngフォルダを作成し、そちらに各画像を配置します。
そして猫認証クラスを作成。
catAuth.class.php
<?php //初期設定 define('CAT_BASE_DIR',dirname(__FILE__).'/'); define('CAT_DIR',CAT_BASE_DIR.'cat/'); define('CAT_OK_DIR',CAT_BASE_DIR.'cat_ok/'); define('CAT_NG_DIR',CAT_BASE_DIR.'cat_ng/'); class catAuthModel { //メンバ変数 private $options=array(); private $images=array(); //コンストラクタ public function __construct(){ //前回の画像削除 $image_file=scandir(CAT_DIR); foreach($image_file as $val){ if($val=='.' || $val=='..'){continue;} unlink(CAT_DIR.$val); } //デフォルト指定 $this->options = array( 'cat_ok' => '1', 'cat_ng' => '3', ); } //設定を上書きセット public function setOptions($options=array()){ foreach($options as $key=>$val){ $this->options[$key]=$val; } return true; } //出力用画像作成 public function makeCats(){ $this->makeOKCats(); $this->makeNGCats(); shuffle($this->images); return $this->images; } //OK画像作成ルーチン private function makeOKCats(){ //OK画像一覧 $cat_ok_dir=scandir(CAT_OK_DIR); foreach($cat_ok_dir as $key=>$val){ if($val=='.' || $val=='..'){unset($cat_ok_dir[$key]);} } //OK画像選択 if($this->options['cat_ok']==1){ $cat_ok_key[]=array_rand($cat_ok_dir,$this->options['cat_ok']); }else{ $cat_ok_key=array_rand($cat_ok_dir,$this->options['cat_ok']); } //OK画像コピー foreach($cat_ok_key as $val){ $file_rand='ok_'.rand(); copy(CAT_OK_DIR.$cat_ok_dir[$val],CAT_DIR.md5($file_rand.$cat_ok_dir[$val])); $this->images[]=array('flg'=>'1','filename'=>CAT_DIR.md5($file_rand.$cat_ok_dir[$val])); } } //NG画像作成ルーチン private function makeNGCats(){ //NG画像一覧 $cat_ng_dir=scandir(CAT_NG_DIR); foreach($cat_ng_dir as $key=>$val){ if($val=='.' || $val=='..'){unset($cat_ng_dir[$key]);} } //NG画像選択 if($this->options['cat_ng']==1){ $cat_ng_key[]=array_rand($cat_ng_dir,$this->options['cat_ng']); }else{ $cat_ng_key=array_rand($cat_ng_dir,$this->options['cat_ng']); } //NG画像コピー foreach($cat_ng_key as $val){ $file_rand='ng_'.rand(); copy(CAT_NG_DIR.$cat_ng_dir[$val],CAT_DIR.md5($file_rand.$cat_ng_dir[$val])); $this->images[]=array('flg'=>'0','filename'=>CAT_DIR.md5($file_rand.$cat_ng_dir[$val])); } } #↓クラスのおわり } |
設定できるオプションはcat_okとcat_ngのふたつで、それぞれ正解画像の枚数と間違い画像の枚数となります。
makeOKCats()とmakeNGCats()は全く同じことをやってるので引数なりforeachなりで纏められるのは確定的に明らかなのですが、まあいいや。
array_randはエントリが複数の場合配列で返りますが、ひとつの場合は何故か配列ではなくキーだけが返ってくるので一々チェックして配列に揃える作業が必要です。
そのまま使用するには問題となる部分がいくつかあります。
CAT_BASE_DIRは実行環境にあわせて書き換える必要があります。
排他制御をしていないので、同時に複数のアクセスがあった場合どんな挙動をするかわかりません。
cat_okやcat_ngに存在する画像枚数より多い数を指定するとエラーになります。
0以下の値とか文字列とかを入れてもエラーになります。
次にこの猫認証クラスを表示する部分。
cat.php
<?php print("<pre>");var_dump($_SESSION['images']); <!--[if IE]><script type="text/javascript"> |
最後にくっついているJavaScriptは、IEではlabelタグでimageタグを括っても機能してくれないというバグの対処用です。
↓のスクリプトをそのまま使わせて頂きました。
http://www.nitoka.net/archives/2006/08/ieimglabel.html
このまま実装すると、ひとつだけチェックを入れて認証失敗した場合、リロードすると1/4の確率で認証成功してしまいます。
裏でワンタイムトークンを発行するなど別の対策が必要となります。
適当にセッションに突っ込めばいいだけですが、まあ所詮個人レベルですのでそこまでする必要もないでしょう。
エラー処理とか細かい部分は端折っていますが、とりあえず猫認証が完成しました。
あとはレイアウトを揃えるなりJavaScriptで飾り立てるなりしてみてください。