»ä¤¿¤Á¤¬Æüº¢»È¤Ã¤Æ¤¤¤ë¥Í¥Ã¥È¾å¤Î¥µ¡¼¥Ó¥¹¤Ç¡¢web ¾å¤Î¥Õ¥©¡¼¥à¤ÎºÇ¸åÅù¤Ë¡Ö¤³¤³¤Ë½ñ¤«¤ì¤Æ¤¤¤ëʸ»ú¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤¡×¤Î¤è¤¦¤Ë¡¢³¨¤ËÉÁ¤«¤ì¤¿Ê¸»ú¤òÌܤÇÆɤ߼è¤Ã¤ÆÆþÎϤ¹¤ë¤è¤¦µá¤á¤é¤ì¤ë¾ì¹ç¤¬¤¢¤ê¤Þ¤¹¡£
¸À¤¦¤Þ¤Ç¤â¤¢¤ê¤Þ¤»¤ó¤¬¡¢¤³¤ì¤ÏÄ̾Ρ֥¥ã¥×¥Á¥ã (CAPTCHA)¡×¤È¸Æ¤Ð¤ì¤Æ¤¤¤ë¤â¤Î¤Ç¡¢²èÁü¥Ç¡¼¥¿¤Ï¡¢¿Í´Ö¤Ê¤é¤½¤ì¤òÆù´ã¤Çǧ¼±¤·¤ÆÆþÎϤ¬¹Ô¤Ê¤¨¤Þ¤¹¤¬¡¢µ¡³£¤Ë¤Ï¾¯¤·Æñ¤·¤¯¤Ê¤ë¤¿¤á¡¢¥Õ¥©¡¼¥à¤Ëʸ»ú¤òÆþÎϤ·¤Æ¤¤¤ë¤Î¤¬¡¢µ¡³£¤Ç¤Ï¤Ê¤¤¤³¤È¤òȽÄꤹ¤ë¤¿¤á¤Ë¤³¤¦¤¤¤¦»ÅÁȤߤ¬Â¸ºß¤·¤Þ¤¹¡£
À¤¤ÎÃæ¤Ë¤¢¤ë CAPTCHA ¤Ï¡¢¤ä¤¿¤é¤È»ú¤¬¥°¥Á¥ã¥°¥Á¥ã¤ÇÆɤ߼è¤ë¤Î¤¬Èó¾ï¤Ëº¤Æñ¤Ê¥±¡¼¥¹¤â¤¢¤ê¤Þ¤¹¡£
¤³¤ì¤ÏÅöÁ³¡¢°Â°×¤Ë¡¢ÇòÃϤ˹õ¤¤Ê¸»ú¤ò½ñ¤¤¤¿¤è¤¦¤Êñ½ã¤Ê²èÁü¤ò CAPTCHA ¤ËÍѤ¤¤ì¤Ð¡¢¤½¤ì¤ò²òÆɤ¹¤ë¥·¥¹¥Æ¥à¤Ï´Êñ¤Ë³«È¯½ÐÍè¤Æ¤·¤Þ¤¤¤Þ¤¹¤Î¤Ç¡¢¡ÖÆù´ã¤Çǧ¼±¡×¤ò¤·¤Æ¤¤¤Ê¤¤µ¡³£¤¬¤³¤Î¥Õ¥©¡¼¥à¤òÄ̲ᤷ¤Æ¤·¤Þ¤¤¤Þ¤¹¡£¤½¤ì¤òËɤ°¤¿¤á¤Ë¤ï¤¶¤È²òÆɤ·¤Ë¤¯¤¤¤è¤¦¤Ë¤½¤¦¤·¤Æ¤¤¤ë¤Î¤Ç¤¹¡£
²òÆɤ·¤Ë¤¯¤¤¤è¤¦¤Ë¤¹¤ë¹©ÉפȤ¤¤¨¤Ð¡¢¤¶¤Ã¤È
- ɽ¼¨¿§¤òÊѤ¨¤ë
- ¥É¥Ã¥È¤äÀþ¤Ê¤É¤ÎÉÔµ¬Â§¤Ê¥Î¥¤¥º¤ò²Ã¤¨¤ë
- ¥Õ¥©¥ó¥È¤ò¿ô¼ïÎà»È¤¦
- ʸ»ú¤Îɽ¼¨°ÌÃÖ¤ò·¤¨¤Ê¤¤
- ʸ»ú¤ò¤Ò¤Í¤ë
²æ¡¹¤¬Ä󶡤¹¤ë livedoor ¤Î¥·¥¹¥Æ¥à¤Ï¡¢¼ç¤Ë Perl ¤Ç³«È¯¤µ¤ì¤Æ¤ª¤ê¡¢Perl ¤Ç CAPTCHA ¤òÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï¡¢GD::SecurityImage ¤È¤¤¤¦ CPAN ¥â¥¸¥å¡¼¥ë¤¬¹¤¯»ÈÍѤµ¤ì¤Æ¤¤¤Þ¤¹¡£
¤³¤Î¥â¥¸¥å¡¼¥ë¤Ï¡¢GD ¤ä Image::Magick ¤ò¥Ð¥Ã¥¯¥¨¥ó¥É¤È¤·¤ÆÍøÍѽÐÍè¤Þ¤¹¤¬¡¢GD ¤È¤« Image::Magick ¤È¤«¤Ã¤Æ¡¢¼ã´³¥¤¥Þ¥É¥¤Ç¤Ï¤Ê¤¤´¶¤¬¤¢¤Ã¤Æ¡¢¤³¤Î¥â¥¸¥å¡¼¥ë¤ò»È¤¦¤¿¤á¤À¤±¤Ë¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¤Î¤Ï¤¢¤Þ¤ê´ò¤·¤¯¤¢¤ê¤Þ¤»¤ó¡£
¤È¤ê¤¢¤¨¤º¡¢¤½¤ó¤ÊÍýͳ¤«¤é¡¢GD Åù¤è¤ê¤â¥â¥À¥ó¤Ê Imager ¤ò»È¤Ã¤Æ¡¢CAPTCHA ¤òºî¤Ã¤Æ¤ß¤¿¤¤¤È¤ª¤â¤¤¤Þ¤¹¡£
¤Ä¤¤¤Ç¤Ë¸À¤¦¤È¡¢»äã¤ÏÆüËܿ͸þ¤±¤Î¥µ¡¼¥Ó¥¹¤ò¼ç¤Ëºî¤Ã¤Æ¤¤¤Þ¤¹¤Î¤Ç¡¢¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È¤ä¿ô»ú¤ÎÁȤ߹ç¤ï¤»¤Î¤ß¤Î CAPTCHA ¤è¤ê¤Ï¡¢ÆüËܸìʸ»ú¤ò»È¤Ã¤¿¤Û¤¦¤¬¡¢ÈóÆüËܸì·÷¤«¤é¤Î¥¢¥¿¥Ã¥¯¤¬¸º¤ë¤·¡¢¤è¤ê°ìÁص¡³£¤Ë¤è¤ë²òÆɤ¬º¤Æñ¤Ë¤Ê¤ë¤Î¤Ç¤Ï¡©¤È²¿µ¤¤Ê¤¯»×¤¤¤Ä¤¤Þ¤·¤¿¡£
GD::SecurityImage ¤ÇÆüËܸì¤ò°·¤¦¤Î¤Ï¤É¤¦¤â°ì¶ÚÆì¤Ç¤Ï¤¤¤«¤Ê¤¤¤è¤¦¤Ç¤¹¤¬¡¢Imager ¤ò»È¤Ã¤Æ¼«ºî¤·¤Æ¤·¤Þ¤¨¤Ð´Êñ¤Ë½ÐÍ褽¤¦¤Êµ¤¤â¤·¤Þ¤¹¡£
¤È¤¤¤¦¤³¤È¤Ç¡¢º£²ó¤Ï Imager ¤Ç CAPTCHA ¤òºî¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
#!perl use strict; use warnings; use POSIX qw(floor); use Imager; my $width = 250; # CAPTCHA ¤ÎÉý my $height = 50; # CAPTCHA ¤Î¹â¤µ # 2 ¤Ä¤Î°ú¿ô¤Î´Ö¤ÎÀ°¿ô¤ò¥é¥ó¥À¥à¤ÇÊÖ¤¹ sub random { my($min, $max) = sort { $a <=> $b } @_; return floor($min + rand($max - $min + 1)); } # 2 ¤Ä¤Î¿§¤Î´Ö¤Î¿§¤ò¥é¥ó¥À¥à¤ÇÊÖ¤¹ sub random_color { my($color_a, $color_b) = @_; my @rgb_a = map { hex $_ } $color_a =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i; my @rgb_b = map { hex $_ } $color_b =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i; my $r = random($rgb_a[0], $rgb_b[0]); my $g = random($rgb_a[1], $rgb_b[1]); my $b = random($rgb_a[2], $rgb_b[2]); return sprintf '#%02x%02x%02x', $r, $g, $b; } # CAPTCHA ¤òºî¤ë my $imager = Imager->new(xsize => $width, ysize => $height); $imager->box(filled => 1, color => random_color('#cccccc', '#ffffff'));¤È¤ê¤¢¤¨¤º¡¢¤³¤ó¤Ê¤ó¤·¤Æ¤ª¤¤¤Æ¡¢
$imager->write(file => 'captcha.png', type => 'png');¤¹¤ë¤È¡¢
¤³¤Î¤è¤¦¤Ê²£ 250 x 50 ¤ÎŬÅö¤Ê¿§¤Î»Í³Ñ¤¬½ÐÍè¤Þ¤·¤¿¡£
¤¢¡¢¤Á¤Ê¤ß¤Ë¡¢¤³¤ì¤Ï¼Â¹Ô¤¹¤ë¤¿¤Ó¤Ë¿§¤¬¥³¥í¥³¥í¤«¤ï¤ê¤Þ¤¹¡£
¤Ç¤Ï¡¢¤³¤³¤Ë 200 ¡Á 300 ¸ÄÄøÅ٤Υ֥ĥ֥Ĥò²Ã¤¨¤Æ¡¢¥³¥ó¥Ë¥ã¥¯¤Ã¤Ý¤¯¤·¤Þ¤¹¡£
for (1 .. random(200, 300)) { $imager->setpixel( x => random(0, $width - 1), y => random(0, $height - 1), color => random_color('#000000', '#666666'), ); }
¤Þ¤µ¤Ë¥³¥ó¥Ë¥ã¥¯¤Ã¤Ý¤¯¤Ê¤ê¤Þ¤·¤¿¤±¤É¡¢¤Ê¤ó¤«¡¢ÅÀ¤¬¥É¥Ã¥È´¶¤¬¶¯¤¯¤Æ·ù¤Ê´¶¤¸¤Ê¤Î¤Ç¡¢·Ú¤¯¥¬¥¦¥¹¤Ü¤«¤·¤ò¤«¤±¤Þ¤¹¡£
$imager->filter(type => 'gaussian', stddev => 0.5);
¤è¤ê°ìÁØ¥³¥ó¥Ë¥ã¥¯¤Ã¤Ý¤¯¤Ê¤ê¤Þ¤·¤¿¡£¤ª¤¤¤·¤½¤¦¡£
¼¡¤ËŬÅö¤ÊÀþ¤ò 3 ¡Á 5 ËÜÄøÅÙÆþ¤ì¤Þ¤¹¡£
for (1 .. random(3, 5)) { $imager->line( color => random_color('#000000', '#666666'), x1 => random(0, $width - 1), y1 => random(0, $height - 1), x2 => random(0, $width - 1), y2 => random(0, $height - 1), aa => 1, ); }
¤¤¤¤´¶¤¸¤Ç¼ÙË⤯¤µ¤¤Àþ¤¬¸½¤ì¤Þ¤·¤¿¡£
¼¡¤Ë¤¤¤è¤¤¤èʸ»ú¤òÆþ¤ì¤ë¤Î¤Ç¤¹¤¬¡¢Å¬Åö¤Êʸ»ú¤òÊÖ¤¹´Ø¿ô¤òºî¤ê¤Þ¤¹¡£
¤Ò¤é¤¬¤Ê¤È¥«¥¿¥«¥Ê¤òÊÖ¤¹¤è¤¦¤Ë¤·¤Þ¤·¤ç¤¦¡£
use List::Util qw(shuffle); use utf8; sub random_char { my($min, $max) = @_; my $length = random($min, $max); my @chr = (); push @chr, map { chr($_) } (ord('¤¢') .. ord('¤ó')); push @chr, map { chr($_) } (ord('¥¢') .. ord('¥ó')); return join '', (shuffle(@chr))[0 .. $length - 1]; }¤³¤ì¤Ç¡¢
random_char()
¤ò¸Æ¤Ó½Ð¤¹¤È¡¢»ØÄꤷ¤¿Ê¸»ú¿ôÆâ¤ÇŬÅö¤ËÁȤ߹ç¤ï¤»¤¿¤Ò¤é¤¬¤Ê¤È¥«¥¿¥«¥Ê¤òÁȤ߹ç¤ï¤»¤¿Ã±¸ì¤¬ÊÖ¤ê¤Þ¤¹¡£¼¡¤Ë¥Õ¥©¥ó¥È¤Î¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¤Þ¤¹¡£
use Imager::Font; my @fonts = map { sprintf '/path/to/%s.ttc', $_ } qw(msgothic msmincho); my $font = Imager::Font->new( file => (shuffle(@fonts))[0], size => 35, aa => 1, type => 'ft2', ); my $word; my $bbox; while (1) { $word = random_char(5, 8); $bbox = $font->bounding_box(string => $word); next if $bbox->total_width >= $width; last; }5 ¡Á 8 ʸ»úÄøÅ٤Υé¥ó¥À¥à¤Êʸ»ú¤òºî¤ê¤Þ¤¹¤¬¡¢Ê¸»ú¤òÀ¸À®¤·¤¿»þ¤Ë¡¢Ê¸»ú¤Îɽ¼¨Éý¤¬Á´ÂÎÏȤÎÂ礤µ¤òĶ¤¨¤Ê¤¤¤è¤¦¤Ë¡¢¥Ï¥ß½Ð¤¿¾ì¹ç¤Ï¤â¤¦°ìÅÙÊ̤Îñ¸ì¤òºî¤ë¤è¤¦¤Ë¤·¤Þ¤¹¡£
¤½¤·¤Æ¡¢Ã±¸ì¤¬·èÄꤷ¤¿¤é¡¢Ê¸»ú¤ò²Ã¹©¤·¤Ê¤¬¤é°ìʸ»ú°ìʸ»ú¾è¤»¤Æ¤¤¤¤Þ¤¹¡£
use Imager::Matrix2d; my $x = floor(($width - $bbox->total_width) / 2); for my $char (split //, $word) { my $bbox = $font->bounding_box(string => $char); # ·Ú¤¯¥Ò¥Í¥ê¤ò²Ã¤¨¤Þ¤¹ my $matrix = Imager::Matrix2d->shear( x => (random(-3, 3) / 10), y => (random(-3, 3) / 10), ); $font->transform(matrix => $matrix); # ¹â¤µ¤Ï¥é¥ó¥À¥à¤ËÇÛÃÖ¤·¤Þ¤¹ my $y = random(10, floor($height - $bbox->font_height) * 2 - 10); $imager->string( align => 0, x => $x, y => $y, halign => 'center', string => $char, font => $font, color => random_color('#000000', '#666666'), ); $x += $bbox->total_width; }
¤â¤¦¡¢¤³¤Î»þÅÀ¤Ç¤À¤¤¤Ö CAPTCHA ¤È¤·¤Æ½½Ê¬¤Ê¤â¤Î¤¬½ÐÍè¾å¤¬¤ê¤Þ¤·¤¿¡£
¤·¤«¤·¡¢Ê¸»ú¤¬°ìÈÖ¾å¤Ë¤¢¤ë¤Î¤Ç¡¢¿§¤òé¤ë¤Èʸ»ú¤¬²òÆɽÐÍ褽¤¦¤Ê´¶¤¸¤Ê¤Î¤Ç¡¢¤½¤Î¾å¤ËÈ碌¤ëÊ̤ΥΥ¤¥º¤â²Ã¤¨¤Æ¤ª¤¤Þ¤¹¡£
for (1 .. random(10, 15)) { my $angle = random(0, 360); my $x = random(0, $width); my $y = random(0, $height); my $radius = random(0, $width - $x); $imager->arc( color => random_color('#000000', '#666666'), x => $x, y => $y, r => $radius, d1 => $angle, d2 => $angle + 1, aa => 1, ); }
¤³¤ó¤Ê´¶¤¸¤Ç¡¢¤È¤ê¤¢¤¨¤º¡¢¤À¤¤¤Ö CAPTCHA ¤Ã¤Ý¤¯¤Ê¤ê¤Þ¤·¤¿¤Í¡£
º£²ó¤Ï Imager ¤ò»È¤Ã¤Æ CAPTCHA Ū¤Ê¤â¤Î¤ò´Êñ¤Ëºî¤ë¼ê½ç¤Î¾Ò²ð¤Ë¤«¤³¤Ä¤±¡¢¤Ê¤ó¤È¤Ê¤¯°ìÅÙºî¤Ã¤Æ¤ß¤¿¤«¤Ã¤¿ÆüËܸì CAPTCHA ¤òºî¤Ã¤Æ¤ß¤Þ¤·¤¿¡£
¼ÂºÝ¤Ë¤³¤ì¤ò CAPTCHA ¤È¤·¤Æ¥Õ¥©¡¼¥à¤ÇÍøÍѤ¹¤ë¾ì¹ç¤Ï¡¢²èÁü¤ò¤É¤Î¤è¤¦¤Ë½ÐÎϤ¹¤ë¤« (¥Õ¥¡¥¤¥ë¤òÅǤ½Ð¤¹¤«¡¢WAF ¤ÎÃ椫¤é¤½¤Î¤Þ¤Þ²èÁü¥Ç¡¼¥¿¤ò½ÐÎϤ¹¤ë¤Î¤«¤È¤«¡¢¥¥ã¥Ã¥·¥å¤È¤«¤É¤¦¤¹¤ë¤Î¤«¤È¤«) ¤ä¡¢ËÜÅö¤ËÆüËܸì¤Ç¤¤¤¤¤Î¤« (¿ô»ú¤À¤±¤Ë¤¹¤ë¤È¤«¡¢±Ñ¸ì¤Ë¤¹¤ë¤Ê¤é¥é¥ó¥À¥à¤Ë¤¹¤ë¤Î¤«¤È¤«¡¢
/usr/share/dict/words
Åù¤«¤éŬÅö¤Êñ¸ì¤ò°ú¤ÃÄ¥¤Ã¤Æ¤¯¤ë¤è¤¦¤Ë¤¹¤ë¤Î¤«¤È¤«) ¤ä¡¢Ê¶¤é¤ï¤·¤¤Ê¸»ú (Ù¹²»¤äÂ¥²»¡¢ÂùÅÀ¤äȾÂùÅÀ) ¤ò´Þ¤á¤ë¤Î¤«¡¢¥Õ¥©¡¼¥à¤«¤é submit ¤µ¤ì¤¿Ê¸»ú¤Î validation ÊýË¡¤ò¤É¤¦¤¹¤ë¤Î¤«¡¢Åù¡¹¤Ë¤Ä¤¤¤Æ¹Íθ¤¹¤ëɬÍפ¬¤¢¤ê¡¢¤³¤ì¤òɽ¼¨¤¹¤ë¤À¤±¤ÇºÑ¤àÌäÂê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¡¢¤³¤ì¤ò¸µ¤Ë Imager ¤ò»È¤Ã¤Æ¤¢¤Ê¤¿¹¥¤ß¤Î CAPTCHA ¤òºî¤é¤ì¤Æ¤ß¤Æ¤Ï¤¤¤«¤¬¤Ç¤·¤ç¤¦¤«¡£¤½¤ì¤Ç¤Ïº£Ç¯¤â¤è¤í¤·¤¯¤ª´ê¤¤¤·¤Þ¤¹¡£
#!perl use strict; use warnings; use utf8; use POSIX qw(floor); use Imager; use Imager::Font; use Imager::Matrix2d; use List::Util qw(shuffle); my $width = 250; # CAPTCHA ¤ÎÉý my $height = 50; # CAPTCHA ¤Î¹â¤µ # 2 ¤Ä¤Î°ú¿ô¤Î´Ö¤ÎÀ°¿ô¤ò¥é¥ó¥À¥à¤ÇÊÖ¤¹ sub random { my($min, $max) = sort { $a <=> $b } @_; return floor($min + rand($max - $min + 1)); } # 2 ¤Ä¤Î¿§¤Î´Ö¤Î¿§¤ò¥é¥ó¥À¥à¤ÇÊÖ¤¹ sub random_color { my($color_a, $color_b) = @_; my @rgb_a = map { hex $_ } $color_a =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i; my @rgb_b = map { hex $_ } $color_b =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i; my $r = random($rgb_a[0], $rgb_b[0]); my $g = random($rgb_a[1], $rgb_b[1]); my $b = random($rgb_a[2], $rgb_b[2]); return sprintf '#%02x%02x%02x', $r, $g, $b; } # CAPTCHA ¤òºî¤ë my $imager = Imager->new(xsize => $width, ysize => $height); $imager->box(filled => 1, color => random_color('#cccccc', '#ffffff')); for (1 .. random(200, 300)) { $imager->setpixel( x => random(0, $width - 1), y => random(0, $height - 1), color => random_color('#000000', '#666666'), ); } $imager->filter(type => 'gaussian', stddev => 0.5); for (1 .. random(3, 5)) { $imager->line( color => random_color('#000000', '#666666'), x1 => random(0, $width - 1), y1 => random(0, $height - 1), x2 => random(0, $width - 1), y2 => random(0, $height - 1), aa => 1, ); } sub random_char { my($min, $max) = @_; my $length = random($min, $max); my @chr = (); push @chr, map { chr($_) } (ord('¤¢') .. ord('¤ó')); push @chr, map { chr($_) } (ord('¥¢') .. ord('¥ó')); return join '', (shuffle(@chr))[0 .. $length - 1]; } my @fonts = map { sprintf '/path/to/%s.ttc', $_ } qw(msgothic msmincho); my $font = Imager::Font->new( file => (shuffle(@fonts))[0], size => 35, aa => 1, type => 'ft2', ); my $word; my $bbox; while (1) { $word = random_char(5, 10); $bbox = $font->bounding_box(string => $word); next if $bbox->total_width >= $width; last; } my $x = floor(($width - $bbox->total_width) / 2); for my $char (split //, $word) { my $bbox = $font->bounding_box(string => $char); # ·Ú¤¯¥Ò¥Í¥ê¤ò²Ã¤¨¤Þ¤¹ my $matrix = Imager::Matrix2d->shear( x => (random(-3, 3) / 10), y => (random(-3, 3) / 10), ); $font->transform(matrix => $matrix); # ¹â¤µ¤Ï¥é¥ó¥À¥à¤ËÇÛÃÖ¤·¤Þ¤¹ my $y = random(10, floor($height - $bbox->font_height) * 2 - 10); $imager->string( align => 0, x => $x, y => $y, halign => 'center', string => $char, font => $font, color => random_color('#000000', '#666666'), ); $x += $bbox->total_width; } for (1 .. random(10, 15)) { my $angle = random(0, 360); my $x = random(0, $width); my $y = random(0, $height); my $radius = random(0, $width - $x); $imager->arc( color => random_color('#000000', '#666666'), x => $x, y => $y, r => $radius, d1 => $angle, d2 => $angle + 1, aa => 1, ); } $imager->write(file => 'captcha.png', type => 'png');