まずは試してみる
試してみたい場合は、以下URLをクリック
サンプルサイト
PHPのGD2が有効でなければなりません
PHPのphp.iniファイルを編集して拡張機能「GD2」を有効にしてください。
;Linuxの場合 extension=gd2 ;Windowsの場合 extension=php_gd2.dll
TrueTypeFontファイルが必要
TrueTypeFontファイルが必要です。
ipaフォント(https://moji.or.jp/ipafont/ipaex00401/)等の無料のフォントをライセンスに準拠してダウンロードして使用しましょう
ソースコード
画像表示と入力フォーム
php_auth_image.php
<?php /* php_auth_image.php */ include("./mam_auth_image.php"); [$auth_char,$auth_img]=getCharImg(); //セッションを開始 session_start(); //セッション変数に正解の文字列を入れておき、 //POST後URLで入力値とPOST値を比較して認証する $_SESSION["img_auth_char"]=$auth_char; if(isset($_GET["result"])&&$_GET["result"]=="failed"){$err="認証失敗<br>";}else{$err="";} ?> <html lang="ja"> <head> <meta charset="UTF-8"> <title>BOT対策用画像認証入力画面</title> </head> <body style="margin:0;background-color:#ffffff"> <form method="post" action="php_auth_image_confirm.php"> <?php if(isset($err)){echo "<p style='color:red;'>{$err}</p>";}?> <img id="char" src="<?=$auth_img;?>"><br> 上記画像に表示された数字を入力してください。<br> <input type="text" maxlength="10" size="20" style="ime-mode:disabled;" name="input_char"><br> <input type="submit" value="認証"> </form> </body> </html>
認証する画面
php_auth_image_confirm.php
<?php /* php_auth_image_confirm.php */ //セッションを開始 session_start(); //セッション変数の正解の文字列を取得 if(isset($_SESSION["img_auth_char"])){$auth_char=$_SESSION["img_auth_char"];}else{$auth_char='';} //postされた文字列を取得 if(!empty($auth_char)&&isset($_POST["input_char"])){$input_char=$_POST["input_char"];}else{$input_char="";} //認証の検証 if($input_char==$auth_char){$auth=true;}else{$auth=false;} if($auth==false){header("location: ./php_auth_image.php?result=failed");} ?> <html lang="ja"> <head> <meta charset="UTF-8"> <title>BOT対策用画像認証結果</title> </head> <body style="margin:0;background-color:#ffffff"> 認証しました </body> </html>
認証画像を生成する関数
mam_auth_image.php
<?php /* mam_auth_image.php */ //TrueTypeFontファイルのパスを指定する。 //ipaフォント(https://moji.or.jp/ipafont/ipaex00401/)を //ライセンスに準拠してダウンロードして使用しましょう define("TrueTypeFontPath",__DIR__."/ipaexg.ttf"); define("ImageHeight",80);//出力される画像の高さ(px) function getCharImg(){ //認証に使用する文字一覧を指定 //半角数字の場合 //1,7は回転すると分かりにくいのでコメントアウト $carr=[/*"1",*/"2","3","4","5","6",/*"7",*/"8","9","0",]; //半角大文字アルファベットの場合 I,Lはコメントアウト //$carr=[ //"A","B","C","D","E","F","G","H",/*"I",*/"J","K",/*"L",*/ //"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z" //]; //全角ひらがなの場合 //「く,て,へ」は回転すると判別しにくいのでコメントアウト //$carr=[ //"あ","い","う","え","お","か","き",/*"く",*/"け","こ", //"さ","し","す","せ","そ","た","ち","つ",/*"て",*/"と", //"な","に","ぬ","ね","の","は","ひ","ふ",/*"へ",*/"ほ", //"ま","み","む","め","も","や","ゆ","よ", //"ら","り","る","れ","ろ","わ","を","ん", //]; $cnum=random_int(6,6);//認証に使用する文字数を指定、とりあえず6桁固定 $cc=''; $c=[]; for($i=0;$i<$cnum;$i++){ $c[$i]=[]; $c[$i]['chr']=$carr[random_int(0,count($carr)-1)]; $cc.=$c[$i]['chr']; } $lt=floor(ImageHeight*0.1);//総画像幅の計算 $img=imagecreatetruecolor(100,100); $dpi=96;//解像度の設定 imageresolution($img, $dpi, $dpi); $pt= floor(ImageHeight*0.6*72/$dpi); $col=imagecolorallocate($img,0,0,0); for($i=0;$i<$cnum;$i++){ //回転角の設定 $c[$i]['r']=random_int(-45,45); $arr=imagettftext( $img,$pt, $c[$i]['r'],0,0, $col,TrueTypeFontPath,$c[$i]['chr'] ); $xmin=min($arr[0],$arr[2],$arr[4],$arr[6]); $xmax=max($arr[0],$arr[2],$arr[4],$arr[6]); $ymin=min($arr[1],$arr[3],$arr[5],$arr[7]); $ymax=max($arr[1],$arr[3],$arr[5],$arr[7]); $c[$i]['x']=$lt-round($xmin*$dpi/72); $char_w=($xmax-$xmin)*$dpi/72; $lt=round($c[$i]['x']+$char_w); //若干文字をかぶせる $lt-=random_int($char_w*0.1,$char_w*0.4); $c[$i]['y']=random_int(floor(ImageHeight*0.1),floor(ImageHeight*0.3))-$ymin; } $lt+=floor(ImageHeight*0.1);//総画像幅の計算 imagedestroy($img); $im=imagecreatetruecolor($lt,ImageHeight); imageresolution($im, $dpi, $dpi); $tranColor = imagecolorallocate($im, 254, 253, 252);//背景色セット imagefill($im, 0, 0, $tranColor); //背景を塗る imagecolortransparent($im,$tranColor);//透明化 //背景にランダムな四角形を描く $rnd=random_int(40,50); for($i=0;$i<$rnd;$i++){ $col=imagecolorallocate($im,random_int(192,255),random_int(192,255),random_int(192,255)); $x1=random_int(0,$lt); $y1=random_int(0,ImageHeight); $x2=random_int($x1,$lt); $y2=random_int($y1,ImageHeight); imagefilledrectangle($im, $x1, $y1, $x2, $y2, $col); } //変形文字を描画する for($i=0;$i<$cnum;$i++){ $col = imagecolorallocate($im, random_int(0,80), random_int(0,80), random_int(0,80));//色 imagettftext( $im, $pt, $c[$i]['r'],$c[$i]['x'],$c[$i]['y'], $col, TrueTypeFontPath, $c[$i]['chr'] ); } //点ノイズの描画 $rnd=random_int(ImageHeight*6,ImageHeight*8); for($i=0;$i<$rnd;$i++){ $col=imagecolorallocate($im,random_int(0,80),random_int(0,80),random_int(0,80)); imagesetpixel($im,random_int(0,$lt),random_int(0,ImageHeight),$col); } //線ノイズの描画 $rnd=random_int(round(ImageHeight*0.8),round(ImageHeight*0.9)); for($i=0;$i<$rnd;$i++){ $col=imagecolorallocate($im,random_int(0,100),random_int(0,100),random_int(0,100)); imageline($im,random_int(0,$lt),random_int(0,ImageHeight),random_int(0,$lt),random_int(0,ImageHeight),$col); } //出力のバッファリングからdata URIを取得 ob_start(); imagejpeg($im,NULL,30); $con = base64_encode(ob_get_contents()); ob_end_clean(); imagedestroy($im); $src="data:image/jpeg;base64,".$con; //わざと少し待つ usleep(500000); //正解の文字列と、画像の配列を返す return [$cc,$src]; }