PHPで画像認証(ひらがな、数字認証等)~ソースコード公開
PHPでBOT対策用の画像認証(ひらがな、数字、アルファベット認証)のソースコードを公開しています。
まずは試してみる
試してみたい場合は、次のURLリンクをクリック
サンプルサイト
ソースコード
PHPのGDが有効でなければなりません
通常、GDが有効だと思いますが、有効でない場合は、
php.iniファイルを編集して拡張機能「GD」を有効にしてください。
TrueTypeFontファイルが必要
TrueTypeFontファイルが必要です。
無料のipaフォント(https://moji.or.jp/ipafont/ipaex00401/)をライセンスに準拠してダウンロードして使用しましょう
認証画像表示と入力フォームの ファイル
php_auth_image.php
<?php include("./mam_auth_image.php"); [$auth_char,$auth_img]=getCharImg(); //セッションを開始 session_start(); //セッション変数に正解の認証文字列を入れて、POST後に入力値とPOST値を比較して認証する $_SESSION["img_auth_char"]=$auth_char; if(isset($_GET["result"])&&$_GET["result"]=="failed"){$err="<p style='color:red;'>認証失敗</p>";}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"> <?=$err?> <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 //セッションを開始 session_start(); //セッション変数の正解の文字列を取得 if(isset($_SESSION["img_auth_char"])){ $img_auth_char=$_SESSION["img_auth_char"]; }else{ die(); } //postされた文字列を取得 if(isset($_POST["input_char"])){ $input_char=$_POST["input_char"]; }else{ $input_char=""; } //認証の検証 if($input_char!==$img_auth_char){ header("location: ./php_auth_image.php?result=failed"; exit; } ?> <html lang="ja"> <head> <meta charset="UTF-8"> <title>BOT対策用画像認証結果</title> </head> <body style="margin:0;background-color:#ffffff"> 認証しました </body> </html>
認証画像を生成するPHPライブラリ ファイル
mam_auth_image.php
getCharImg() 関数を呼び出すと、配列 ["認証文字","認証画像"] を返してきます。
<?php //TrueTypeFontファイルのパスを指定 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]; }