« CGI::App::Plugin::Stashの使いどころ。 | メイン | HTML::FillInForm::ForceUTF8 »

Catalyst::Plugin::Captcha

Captchaの作成とvalidationを行うCatalystのプラグイン

__追記__
id:charsbar氏のはてなブックマークの指摘で、

validateの方はHWとかFVとか組み込んでいる場合が多いだろうからプラグインを分けた方がよいかも。

とあったので、validateメソッドに加えて、sessionに保存されている文字列を取得するcaptcha_stringを加えてみた。
http://nomadscafe.jp/archives/Catalyst-Plugin-Captcha-0.01.tar.gz
__/追記__

package Catalyst::Plugin::Captcha;

use strict;
use warnings;
use GD::SecurityImage;

our $VERSION = '0.01';

sub setup {
    my $c = shift;

    $c->config->{captcha}->{session_name} = 'captcha_string';
    $c->config->{captcha}->{new} ||= {};
    $c->config->{captcha}->{create} ||= [];
    $c->config->{captcha}->{particle} ||= [];

    return $c->NEXT::setup(@_);
}

sub create_captcha {
    my $c = shift;

    my $image = GD::SecurityImage->new(%{$c->config->{captcha}->{new}});
    $image->random();
    $image->create(@{$c->config->{captcha}->{create}});
    $image->particle(@{$c->config->{captcha}->{particle}});

    my ( $image_data, $mime_type, $random_string ) = $image->out;

    $c->session->{ $c->config->{captcha}->{session_name} } = $random_string;
    $c->res->content_type($mime_type);
    $c->res->output($image_data);
}

sub validate_captcha {
    my ($c, $verify) = @_;
    my $string = $c->captcha_string;
    return ($verify && $string && $verify eq $string);
}

sub captcha_string {
    my $c = shift;
    return  $c->session->{ $c->config->{captcha}->{session_name} };
}

1;

使い方としては、Controllerで、create/validate_captcha

MyApp->config->{captcha}->{
    session_name => 'captcha_string',
    new => {
        width => 80,
        height => 30,
        lines => 7,
        gd_font => 'giant',
    },
    create => [qw/normal rect/],
    particle => [100]
};

sub do_post : Local {
    my ( $self, $c ) = @_;
    my $ret = $c->validate_captcha($c->req->params->{validatekey}) ? 1 : 0;
    $c->res->output("output:$ret");
}

sub captcha : Local {
    my ( $self, $c ) = @_;
    $c->create_captcha();
}

#validate with CP::FormValidator::Simple
sub do_post : Local {
      my ($self, $c) = @_;
      $c->form(
          validate => [['EQUAL_TO',$c->captcha_string]]
      )
}


テンプレートは、こんな感じ

<form method="post" action="[% c.uri_for('/do_post') %]">
<input type="text" name="validatekey" id="validatekey" size="10" value="" /><br />
<img src="[% c.uri_for('/captcha') %]"><br />
<input type="submit" value="チェック" /> 
</form>


どうでしょうか。