Infosia, Inc.

インフォシアでは、UNIXプラットフォームを中心とし、Java、C#、PHP 等を利用したソフトウェアの開発を行っています。

  • トップ
  • 会社概要
  • お知らせ
  • ブログ

cakephp 用 CAPTCHA コンポーネント(日本語対応)

8月 5th, 2008

スパムや不正登録防止のために CAPTCHA を使うことはよくあることですが、特に外国からの不正アクセスに関しては日本語(漢字)を入力させる CAPTCHA が有効であるという記事を目にしました。

そこで、漢字やひらがなの表示に対応した、CAPTCHA の cakephp のコンポーネントを作成しました。
MIT ライセンスで公開いたします。

動作イメージ

ひらがなと、小学校一年生で習うレベルの漢字を使った CAPTCHA です。簡単な漢字しか使わないので分かったような分からないような面白い日本語が出力されるのも魅力の一つです :razz:

スクリプトを動作させるには mbstring, freetype, gd に対応した PHP がインストールされている必要があります。日本語の表示には日本語のフォントが必要で、ライセンス上問題ないものを こちら から入手することができます。

作成に際しては以下のサイトを参考にさせていただきました。

http://rossoft.wordpress.com/2006/03/16/image-auth-component/
http://php.to/tips/8/

コンポーネントの使用方法は こちら に詳しく載っていますので参考にしてください。

app/controllers/components/image_auth.php

<?php
/*
 * Image Auth component.
 * Real human verification system for forms with japanese characters
 *
 * @author      RosSoft
 * @author      Infosia, Inc.
 * @version     0.1
 * @license     MIT
 *
 * @link http://rossoft.wordpress.com/2006/03/16/image-auth-component/
 * @link http://www.infosia.co.jp/posts/157
 * @link http://php.to/tips/8/
 */
class ImageAuthComponent extends Object {
    var $components = array('session');
    var $controller;

    var $font = 'ipam';

    var $imageWidth  = 170;
    var $imageHeight = 50;

    var $fontSize    = 16;
    var $letterSpace = 10;

    var $strLength   = 4;

    var $bgColors = array(
        '176.196.222', // Blue
        '204.153.204', // Purple
        '204.204.204', // Gray
        '227.81.82',   // Red
        '150.200.162'  // Green
        );

    var $fontColors = array(
        '0.0.139',    // Blue
        '104.34.139', // Purple
        '79.79.79',   // Gray
        '128.0.0',    // Red
        '59.94.15'    // Green
        );

    function startup(&$controller) {
        $this->controller = $controller;
    }

    function generate($regenerate = true) {
        if (!$regenerate) {
            $regenerate= ! $this->session->check('image_auth_string');
        }
        if ($regenerate) {
            $string = $this->_generateString($this->strLength);
            $this->session->write('image_auth_string', $string);
        }
    }

    function check($str) {
        return ($str === $this->session->read('image_auth_string'));
    }

    function show() {

        $this->generate(false);
        $string = $this->session->read('image_auth_string');

        putenv('GDFONTPATH=' . realpath(VENDORS . 'image_auth'));

        $img = imagecreate($this->imageWidth, $this->imageHeight) or die('Can not initialize GD Image Library');

        list($br, $bg, $bb) = explode('.', $this->bgColors[rand(0, count($this->bgColors)-1)]);
        list($tr, $tg, $tb) = explode('.', $this->fontColors[rand(0, count($this->fontColors)-1)]);

        $bgColor   = imagecolorallocate($img, $br, $bg, $bb);
        $txtColor  = imagecolorallocate($img, $tr, $tg, $tb);
        $lineColor = imagecolorallocate($img, 0, 0, 0);

        imageline($img, 0, 0, $this->imageWidth, 0,  $lineColor);
        imageline($img, 0, 0, 0, $this->imageHeight, $lineColor);
        imageline($img, 0, $this->imageHeight-1, $this->imageWidth, $this->imageHeight -1, $lineColor);
        imageline($img, $this->imageWidth-1, 0, $this->imageWidth-1, $this->imageHeight, $lineColor);

        for($i=0; $i<strlen($string); $i++) {
            imagettftext($img, (rand() % $this->fontSize / 1.5) + $this->fontSize, rand(-40, 00), (($i * $this->fontSize * 2) + $this->letterSpace), rand($this->fontSize+15, ($this->imageHeight - $this->fontSize-15)), $txtColor, $this->font, mb_substr($string, $i, 1, "UTF-8"));
        }

        if (function_exists('imagefilter')) {
            imagefilter($img, IMG_FILTER_GAUSSIAN_BLUR, 200);
        }

        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: no-store, no-cache");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");

        if (function_exists('imagepng')) {
            header("Content-type: image/png");
            imagepng($img);
        } else {
            header("Content-type: image/jpeg");
            imagejpeg($img);
        }
        $this->controller->autoRender=false;
    }

    function _generateString($length = 6) {
        $string = '';
        srand(getmicrotime());
        $s = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんがぎぐげござじずぜぞだぢづでど一右雨円王音下火花貝学気九休玉金空月犬見五口校左三山子四糸字耳七車手十出女小上森人水正生青夕石赤千川先早草足村大男竹中虫町天田土二日入年白八百文木本名目立力林六";
        for($i=0; $i < $length; $i++) {
            $string .= mb_substr($s, rand(1, mb_strlen($s, 'UTF-8') -1), 1, 'UTF-8');
        }
        return $string;
    }

    function getmicrotime(){
        list($usec, $sec) = explode(" ",microtime());
        return ((float)$sec + (float)$usec);
    }

}
?>

ログインコントローラ(サンプル)

<?php
class UsersController extends AppController {
    var $helpers    = array('Html', 'Form');
    var $components = array('imageAuth');
    function add() {
        if (!empty($this->data)) {
// snip...
            if (!$this->imageAuth->check($this->data['User']['image_auth'])) {
                $this->flash('画像に表示されている文字と一致しません', 'javascript:history.back();');
                return;
            }
        }
    }
// snip...
    function image_auth() {
        $this->imageAuth->show();
    }
}
?>

登録フォームテンプレート(サンプル)

<?php
  echo $form->create('User', array('action' => 'add'));
  echo 'メールアドレス: ';
  echo $form->input('User.username', array('type'=>'text', 'label'=>false));
  echo 'パスワード: ';
  echo $form->input('User.password', array('type'=>'password', 'label'=>false, 'value'=>''));
?>
画像に表示されている文字を入力してください
<div class="input text"><img src="<?php echo $html->url('/users/image_auth') ?>" /></div>
<?php
  echo $form->input('User.image_auth', array('type'=>'text', 'label'=>false, 'value'=>''));
  echo $form->submit("新規登録");
  echo $form->end();
?>

Posted in ダウンロード, 札幌で働く社長のブログ | No Comments

Comments are closed.

  • カテゴリー

    • お知らせ (8)
    • ダウンロード (5)
    • 札幌で働く社長のブログ (109)
  • Recent Posts

    • 7期目!
    • 6年目に入りました
    • 初雪&円山に登ってきました
    • 海行ってきました
    • 桜が満開!
    • 「会社やろうぜ」は「バンドやろうぜ」とよく似ている。
  • アーカイブ

    • 2011年7月 (1)
    • 2010年12月 (1)
    • 2010年10月 (1)
    • 2010年7月 (1)
    • 2010年5月 (2)
    • 2010年4月 (1)
    • 2010年3月 (1)
    • 2010年1月 (1)
    • 2009年11月 (3)
    • 2009年7月 (1)
    • 2009年5月 (2)
    • 2009年4月 (3)
  • インフォシアについて

    インフォシアは、インターネットを利用した一般ユーザ向けコミュニティーサイト構築から企業経営効率化のためのバックエンドシステム開発まで、システム開発を通して顧客の企業活動をサポートする会社です。[» 会社概要]

RSS FeedRSS Feed
Infosia, Inc. © 2011 All Rights Reserved.
Back to Top