Linux Install Memo

サーバー管理者によるLinux関連ソフトのインストールメモ

Home » □PHPでフォーム入力時の画像認証(CAPTCHA認証)を導入

□PHPでフォーム入力時の画像認証(CAPTCHA認証)を導入

登録、投稿、コメントなど、とにかくフォームを設置するとあらゆる方法で
機械的に登録してくる輩がいる。そもそも登録してもお前らには意味がない
のだといっても全く聞く耳を持っていない。そりゃそうだ、自動処理をして
いるのだから。

そこでその自動処理を防ぐために(DBその他に無駄な処理をさせないために)
フォーム入力時の画像認証(CAPTCHA認証)を導入したいのだけど、どれも懲り
すぎていたりするのであんまり気に入らない…ので自分で作りました。

スクリプトは二つ。

一つは「POST」で渡された文字列をPNG画像で表示するスクリプト。(keydata.php)
もう一つは、keydata.phpに対してどのように文字を渡し、どのように結果
の画像を表示するかのスクリプト。

前者は表示するだけのスクリプトだけど、POSTで渡さないといけないところ
がミソ。だってGETで渡すようにしたら簡単に機械処理されてしまうからね。
ここでは5文字を想定していますので、もっと長いほうがよかったり短い方
がよかったり、画像を合成したいとかさらに見難くしたいという場合には、
GDの処理をいろいろ調べてあれこれ加工して下さい。

後者は実際に普段の処理側のこと。生で送られてくるPNGデータをどうしたら
PHP処理内で表示できるのがあれこれ見てみたら、こんな方法がありました。
目からうろこでした。

ただ、IE6までは×(FFやChromeとかOperaならぜんぜんOK)というのと、携帯系
は全然使えませんのであしからず。(スマフォはいけました、Androidレグザで)

こちらは画像を表示する(出力する)スクリプト。

<?
// ------------------------------------------------------------
// POSTで送信された文字(または数字)をJPEGで返すスクリプト(画像側)
// 2011.11.01 T.Kabu/Future Versatile Group
//
// ・GDライブラリが組み込まれたPHPでないと動きません
// ・このスクリプトに対してkeydataという変数に文字を入れてPOSTして下さい
// ・読めば判るレベルですが、とりあえず5文字を想定しています
// ・フォントはあえて読みにくい文字にするといいと思います
//   ここではYAKITORIフォントを使っています。
//   http://www.forest.impress.co.jp/docs/review/20110117_420882.html
// ------------------------------------------------------------
?>
<?
// ------------------------------
// 初期処理
// ------------------------------
// 画像サイズ設定
$P_W = 128;
$P_H = 36;

// フォントサイズ設定
$F_S = 28;

// ------------------------------
// データ取得
// ------------------------------
// ポストデータでない場合には
if (!isset($_POST['keydata']))
{
    $KEYDATA = 'ERROR';
}
// ポストデータ
elseif(strlen($_POST['keydata']) == 0)
{
    $KEYDATA = 'NONE';
}
elseif(strlen($_POST['keydata']) < 3)
{
    $KEYDATA = 'SHORT';
}
else
{
    $KEYDATA = $_POST['keydata'];
}

// 画像パレットを生成
$IMG_P = imagecreatetruecolor($P_W, $P_H);

// 白色の背景、オレンジのテキストとして設定
$background_color = imagecolorallocate($IMG_P, 240, 240, 240);
$text_color = imagecolorallocate($IMG_P, 255, 137, 0);

// 背景を赤にします
imagefilledrectangle($IMG_P, 0, 0, $P_W - 1 , $P_H - 1, $background_color);

// ttf フォントファイルへのパスを設定します
//$font_file = '/usr/share/fonts/TrueType-vlgothic/VL-PGothic-Regular.ttf';
$font_file = './Yakitori.otf';

// フォントサイズ 13 で 'PHP Manual' というテキストを描画します
imagefttext($IMG_P, $F_S, 0, 3, $P_H - 3, $text_color, $font_file, $KEYDATA);

// ヘッダ出力(単独で呼び出された時などに上記メッセージの画像を出すため
header('Content-Type: image/jpeg');

// 画像データ出力(劣化させるとますます機械認識は厳しい…かな?
imagejpeg($IMG_P, NULL, 25);

// 画像データ破棄
imagedestroy($IMG_P);
?>

こちらは呼び出すほうのスクリプト。

<?
// ------------------------------------------------------------
// POSTで任意の文字を渡して帰ってきたJPEGデータをbase64エンコードで表示するスクリプト(呼び出し側)
// 2011.11.01 T.Kabu/Future Versatile Group
//
// ・ポストする方法はあちこちにあるけど、今回はこちらを参考にしました
//   http://www.programming-magic.com/20080226023511/
// ・で、画像を表示するには…なるほど、こんな方法あったのねー、です。
//   http://kaworu.jpn.org/kaworu/2008-04-06-1.php
// ------------------------------------------------------------
?>
<?
// 表示したいデータを生成
$KEYDATA = sprintf("%05d", rand(100,99999));
// 表示するデータのクリプトデータを生成
$CRYPTKEY = crypt($KEYDATA, 'HOGEHOGE');

// フルパスで「POSTで送信された文字(または数字)をJPEGで返すスクリプト(画像側)」を指定
$KEYDATA_URL = 'http://hogehoge.comm/keydata.php';
// 画像生成用のキーデータを設定
$REQUEST_PARAM = array('keydata' => $KEYDATA);
// リクエストを生成
$REQUEST_DATA = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($REQUEST_PARAM),
));
// 画像データをリクエストして帰ってきたデータをBASE64でエンコード
$BASE64_IMG = base64_encode(file_get_contents($KEYDATA_URL, false, stream_context_create($REQUEST_DATA)));
?>
<img src="data:image/jpeg;base64,<? print $BASE64_IMG; ?>">
<BR>
<BR>
<FORM action="./" method="post">
<INPUT type="hidden" name="CRYPTKEY" value="<? print $CRYPTKEY; ?>">
<INPUT type="text" name="CHECKKEY" value="" size="10" maxlength="5">
<INPUT type="submit" name="SUBMIT" value="CHECK">
</FORM>
<?
    // クリプトキーとチェックキーがあるなら…チェックをする
    if (isset($_POST['CRYPTKEY']) && isset($_POST['CHECKKEY']))
    {
        // クリプトチェックがOKなら
        if (crypt($_POST['CHECKKEY'], $_POST['CRYPTKEY']) == $_POST['CRYPTKEY'])
        {
            print "チェックOKです!!<BR>\n";
        }
        else
        {
            print "違うみたいです!?<BR>\n";
        }
    }
?>

あとは必要に応じていろいろいじって下さい。

追記:2011/11.01 -1-

yum -y install php-gd

…忘れずに。(肝心のターゲットシステムに入ってなかった)

Name of author

Name: admin

One thought on “□PHPでフォーム入力時の画像認証(CAPTCHA認証)を導入

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です