CAPTCHAスクリプトを作成しました。サイズ、文字数、選択する文字はカスタマイズ可能です。
ここにあるcaptcha.php
:
<?php
function generateCaptcha($num_digits, $challenge_num, $size, $chars, $incode = false) {
if(session_id() == '') session_start();
if(isset($_SESSION['captcha'])) unset($_SESSION['captcha']);
// You *must* type your own random salt here, *DO NOT* use this one.
$salt = 'H#(*h3^rh@(*E%h$W*WK#vMIv)%(D*(A&*W@A^D6@r4*I%u8tgsc#yejdi$d8dee';
$message = '';
if(isset($_POST['hash']) && isset($_POST['code'])) {
if(!empty($_POST['hash']) && !empty($_POST['code']) && !empty($_POST['correct_index'])) {
if(md5($_POST['hash'] . $_POST['code'] . $salt) == $_POST['correct_index']) {
$message = '<p>Correct!</p>';
} else {
$message = 'Incorrect code. Please try again.';
}
}
}
$code = '';
if($incode == false) {
for($i = 0; $i < $num_digits; $i++) {
$digit = substr($chars, floor(mt_rand(0, strlen($chars) - 1)), 1);
while(strpos($code, "$digit") !== false) {
$digit = substr($chars, floor(mt_rand(0, strlen($chars) - 1)), 1);
}
$code .= $digit;
}
} else {
for($i = 0; $i < $num_digits; $i++) {
$digit = substr($incode, floor(mt_rand(0, strlen($incode) - 1)), 1);
while(strpos($code, "$digit") !== false) {
$digit = substr($incode, floor(mt_rand(0, strlen($incode) - 1)), 1);
}
$code .= $digit;
}
}
$parts = str_split($code);
$width = $num_digits * $size;
$height = $size * 2;
$image = imagecreatetruecolor($width, $height);
$background = imagecolorallocate($image, floor(mt_rand(96, 255)), floor(mt_rand(96, 255)), floor(mt_rand(96, 255)));
imagefilledrectangle($image, 0, 0, $width, $height, $background);
$num_spots = floor(mt_rand($size * 2, $size * 15));
for($i = 0; $i < $num_spots; $i++) {
$color = imagecolorallocate($image, floor(mt_rand(30, 255)), floor(mt_rand(30, 255)), floor(mt_rand(30, 255)));
$x = floor(mt_rand(0, $width));
$y = floor(mt_rand(0, $height));
$ellipse_width = floor(mt_rand(0, $size / 2));
$ellipse_height = floor(mt_rand(0, $size / 2));
imagefilledellipse($image, $x, $y, $ellipse_width, $ellipse_height, $color);
$x1 = floor(mt_rand(0, $width));
$y1 = floor(mt_rand(0, $height));
$x2 = floor(mt_rand(0, $width));
$y2 = floor(mt_rand(0, $height));
imageline($image, $x1, $y1, $x2, $y2, $color);
}
$num_dots = floor(mt_rand($size * 50, $size * 80));
for($i = 0; $i < $num_dots; $i++) {
$color = imagecolorallocate($image, floor(mt_rand(30, 255)), floor(mt_rand(30, 255)), floor(mt_rand(30, 255)));
$x = floor(mt_rand(0, $width));
$y = floor(mt_rand(0, $height));
imagesetpixel($image, $x, $y, $color);
}
for($i = 0; $i < count($parts); $i++) {
$color = imagecolorallocate($image, floor(mt_rand(0, 150)), floor(mt_rand(0, 150)), floor(mt_rand(0, 150)));
$x = floor(mt_rand($size * 0.9, $size * 1.1));
$y = floor(mt_rand($size, $size * 2));
imagettftext($image, $size, floor(mt_rand(-10, 10)), $i * $x, $y, $color, 'Justus-Bold.ttf', $parts[$i]);
imagettftext($image, $size, floor(mt_rand(-10, 10)), $i * $x + floor(mt_rand(1, 7)), $y, $color, 'Justus-Bold.ttf', $parts[$i]);
imagettftext($image, $size, floor(mt_rand(-10, 10)), $i * $x + floor(mt_rand(1, 7)), $y, $color, 'Justus-Bold.ttf', $parts[$i]);
imagettftext($image, $size, floor(mt_rand(-10, 10)), $i * $x + floor(mt_rand(1, 7)), $y, $color, 'Justus-Bold.ttf', $parts[$i]);
}
$white = imagecolorallocate($image, 255, 255, 255);
$filename = md5(time() . $_SERVER['REMOTE_ADDR'] . mt_rand(0, 1000)) . '.png';
imagepng($image, $filename);
imagedestroy($image);
$file = file_get_contents($filename);
$imgsize = getimagesize($filename);
unlink($filename);
$captcha = 'data:' . $imgsize['mime'] . ';base64,' . base64_encode($file);
$challenge = array('captcha' => '', 'code' => null, 'size' => 0, 'digits' => 0);
if($incode == false) {
$challenge = generateCaptcha($challenge_num, 0, $size, $chars, $code);
}
$hash = md5($challenge['code'] . $salt);
$correct_index = array();
for($i = 0; $i < strlen($challenge['code']); $i++) {
$correct_index[] = strpos($code, substr($challenge['code'], $i, 1));
}
$result = array(
'captcha' => $captcha,
'challenge' => array($challenge['captcha'], $challenge['size'], $challenge['digits']),
'size' => array($imgsize[0], $imgsize[1]),
'hash' => $hash,
'code' => $code,
'message' => $message,
'width' => $size,
'digits' => $num_digits,
'correct_index' => md5($hash . implode('', $correct_index) . $salt)
);
return $result;
}
?>
...そしてここにありますcaptcha.html
:
<!DOCTYPE HTML>
<!--
<?php
include 'captcha.php';
$captcha = generateCaptcha(4, 2, 100, '0123456789');
?>
-->
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<title>Click-captcha test</title>
<style type="text/css">
#challenge, #captcha-img {
margin: 10px
}
#captcha-img {
overflow: hidden
}
.captcha-digit {
display: block;
float: left;
width: <?php echo $captcha['width']; ?>px;
height: 100%;
cursor: pointer
}
.captcha-digit-selected {
background: #ccc;
opacity: .75;
filter: progid:DXImageTransform.Microsoft.Gradient(StartColorStr='#f2cccccc', EndColorStr='#f2cccccc')
}
</style>
<script type="text/javascript">
var captchaLinks = [];
var digits = [];
var num_digits = <?php echo $captcha['challenge'][2]; ?> - 1;
addEvent(window, 'load', init);
function init() {
captchaLinks = ['<?php
$digits = array();
for($i = 'digit0'; $i < 'digit' . $captcha['digits']; $i++) {
$digits[] = $i;
}
echo implode("', '", $digits);
?>'];
for(var i = 0; i < captchaLinks.length; i++) {
//for(var link in captchaLinks) {
addEvent(document.getElementById(captchaLinks[i]), 'click', newCaptchaDigit);
}
}
function newCaptchaDigit(e) {
if(e.target.className == 'captcha-digit captcha-digit-selected') {
digits.splice(digits.indexOf(e.target.id.substr(-1, 1)), 1);
e.target.className = 'captcha-digit';
} else if(digits.length <= num_digits) {
digits.splice(num_digits, digits.length - num_digits, e.target.id.substr(-1, 1));
e.target.className = 'captcha-digit captcha-digit-selected';
}
document.getElementById('code').value = digits.join('');
}
function addEvent(elem, event, handler) {
if(elem !== null & typeof elem !== 'undefined') {
if(elem.addEventListener) {
elem.addEventListener(event, handler, false);
} else if(elem.attachEvent) {
elem.attachEvent('on' + event, handler);
} else if(elem['on' + event]) {
elem['on' + event] = handler;
}
}
}
</script>
</head>
<body>
<div>
<form action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post">
<div id="captcha">
<div><?php echo $captcha['message']; ?></div>
<div>Click the following number sequence:
<div id="challenge" style="width: <?php echo $captcha['challenge'][1][0]; ?>px; height: <?php echo $captcha['challenge'][1][1]; ?>px; background-image: url('<?php echo $captcha['challenge'][0]; ?>')"></div>
</div>
<div id="captcha-img" style="width: <?php echo $captcha['size'][0]; ?>px; height: <?php echo $captcha['size'][1]; ?>px; background-image: url('<?php echo $captcha['captcha']; ?>')">
<?php for($i = 'digit0'; $i < 'digit' . $captcha['digits']; $i++) { ?>
<a class="captcha-digit" id="<?php echo $i; ?>"></a>
<?php } ?>
</div>
</div>
<input type="hidden" name="hash" value="<?php echo $captcha['hash']; ?>" />
<input type="hidden" name="correct_index" value="<?php echo $captcha['correct_index']; ?>" />
<input type="hidden" name="code" id="code" value="" />
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>
何が起こっているのか見ていただければ幸いですが、ここで説明します。:-)
関数が呼び出されgenerateCaptcha
、パラメータを受け取ります$num_digits, $challenge_num, $size, $chars, $incode = false
。
$num_digits
: CAPTCHA に入れる文字数
$challenge_num
: チャレンジに入れる文字数
$size
: CAPTCHA のサイズ
$chars
: 含める文字 (例: 数字の場合: '0123456789'
)
$incode
: これは、チャレンジを生成するためにスクリプト自体が呼び出されたかどうかをスクリプトが判断できるようにするためです。設定しないでください。
したがって、4 文字、1 文字のチャレンジ (質問のような)、サイズ 30、数字のみの CAPTCHA 画像を作成するには、次のコードを使用します。
<?php
include 'captcha.php';
$captcha = generateCaptcha(4, 1, 30, '0123456789');
?>
次に、変数$captcha
は次のようになります。
array(9) {
["captcha"]=>
string(118058) "data:image/png;base64,iVBORw0KG...kSuQmCC"
["challenge"]=>
array(3) {
[0]=>
string(76266) "data:image/png;base64,iVBORw0KG...kJggg=="
[1]=>
array(2) {
[0]=>
int(200)
[1]=>
int(200)
}
[2]=>
int(2)
}
["size"]=>
array(2) {
[0]=>
int(400)
[1]=>
int(200)
}
["hash"]=>
string(32) "81bc501400b8da366e70b26007cb2323"
["code"]=>
string(4) "4817"
["message"]=>
string(0) ""
["width"]=>
int(100)
["digits"]=>
int(4)
["correct_index"]=>
string(32) "17ae615be69c757505dc7f69fce2afb1"
}
さらに情報が必要な場合は、コメントで質問してください。