不需要GD库的情况下实现验证码,看看这个大家需不需要!

时间:2023-02-22 11:45:54
<?php
//+-------------------------------------------------
//| * 文件  validate_image.php
//| * 功能  实现网站登陆验证码
//| * 版本  1.0.0
//| * 日期  2005-4-1
//| * 作者  西北狼 QQ 500784 cokeyang at hotmail.com
//| * 版权  http://www.adibaby.com[暂时关闭]
//| * 使用方法:
//| 预先做好一些图片,推荐使用GIF格式,文件名与图片里面的
//| 数字一致,将图片放入一个文件夹。设置CONFIG里面的数据.
//| 引用 <IMG SRC="{filepath}/validate_image.php">
//| 验证页面对比
//| $_COOKIE['validate'] == md5($_POST['input'])
//|==================CONFIG START===================
$image_path="numimage"; // 图片文件路径 后面没有'/'
$image_ext ="gif"; // 图片文件扩展名
//===================CONFIG END=====================
$imagelist = array();
if ($handle =opendir($image_path)) {
while (false !== ($file =readdir($handle))) {
$filename =explode(".",$file);
$imagelist[] = $filename[0];
unset($filename);
}
closedir($handle);
unset($imagelist[0]);
unset($imagelist[1]);
}
srand((float)microtime()*10000000);
$filename=$imagelist[array_rand($imagelist)];
setcookie("validate",md5($filename));
header('Content-type: application/'.$image_ext);
echo implode('',file($image_path."/".$filename.".".$image_ext));
?>
如果有什么好的建议!希望大家帮我提出来!

17 个解决方案

#1


多做一些图片效果更好一些!不容易重复!

#2


验证码的目的就是要阻止客户端robot的使用,除非你预设的图片足够多
否则客户端可以通过捕获图片的字节数实现自动获取验证码

#3


snmr_com(麒麟厍人)其实你用FireWork做一些图片你就能看出来!
同样大小的图片,如果只是数字不一样的话!大小几乎都是差不多的!
都是那几个字节,呵呵,几百张图片,几乎都是一样的!所以robot应该是弄不出来!

#4


呵呵,没用GD库,这样也确实是个解决办法.

#5


我在没有GD库的情况,是这样用的,以下代码感谢唠叨提供一个显示时间的程序,我从这个修改过来的,现在可以显示4位数字随机图片。

<?php
//生成数字图象的函数
function draw_digit($x, $y, $digit)
{
global $sx, $sy, $pixels, $digits, $lines;
$digit = $digits[$digit];
$m = 8;
for ($b = 1, $i = 0; $i < 7; $i++, $b *= 2) {
if (($b & $digit) == $b) {
$j = $i * 4;
$x0 = $lines[$j] * $m + $x;
$y0 = $lines[$j + 1] * $m + $y;
$x1 = $lines[$j + 2] * $m + $x;
$y1 = $lines[$j + 3] * $m + $y;
if ($x0 == $x1) {
$ofs = 3 * ($sx * $y0 + $x0);
for ($h = $y0; $h <= $y1; $h++, $ofs += 3 * $sx) {
$pixels[$ofs] = chr(0);
$pixels[$ofs + 1] = chr(0);
$pixels[$ofs + 2] = chr(0);
}
} else {
$ofs = 3 * ($sx * $y0 + $x0);
for ($w = $x0; $w <= $x1; $w++) {
$pixels[$ofs++] = chr(0);
$pixels[$ofs++] = chr(0);
$pixels[$ofs++] = chr(0);
}
}
}
}
}
//将文字加入到图象中
function add_chunk($type)
{
global $result, $data, $chunk, $crc_table;
// chunk :为层
// length: 4 字节: 用来计算 chunk
// chunk type: 4 字节
// chunk data: length bytes
// CRC: 4 字节:  循环冗余码校验
// copy data and create CRC checksum
$len = strlen($data);
$chunk = pack("c*", ($len >> 24) & 255,
($len >> 16) & 255,
($len >> 8) & 255,
$len & 255);
$chunk .= $type;
$chunk .= $data;
// calculate a CRC checksum with the bytes chunk[4..len-1]
$z = 16777215;
$z |= 255 << 24;
$c = $z;
for ($n = 4; $n < strlen($chunk); $n++) {
$c8 = ($c >> 8) & 0xffffff;
$c = $crc_table[($c ^ ord($chunk[$n])) & 0xff] ^ $c8;
}
$crc = $c ^ $z;
$chunk .= chr(($crc >> 24) & 255);
$chunk .= chr(($crc >> 16) & 255);
$chunk .= chr(($crc >> 8) & 255);
$chunk .= chr($crc & 255);
// 将结果加到$result中
$result .= $chunk;
}
//主程序
//$sx = 80;
$sx = strlen($sj)*13+2;
$sy = 21;
$pixels = "";
// 填充
for ($h = 0; $h < $sy; $h++) {
for ($w = 0; $w < $sx; $w++) {
$r = 100 / $sx * $w + 155;
$g = 100 / $sy * $h + 155;
$b = 255 - (100 / ($sx + $sy) * ($w + $h));
$pixels .= chr($r);
$pixels .= chr($g);
$pixels .= chr($b);
}
}
$digits = array(95, 5, 118, 117, 45, 121, 123, 69, 127, 125);
$lines = array(1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 1, 2, 0, 1, 1, 1, 0, 0, 1, 0);
function draw($str){
$k = 3;
for($j=0; $j<strlen($str); $j++) {
draw_digit($k, 2, $str[$j]);
$k+=13;
}
}
draw($sj);
// 创建循环冗余码校验表
$z = -306674912;  // = 0xedb88320
for ($n = 0; $n < 256; $n++) {
$c = $n;
for ($k = 0; $k < 8; $k++) {
$c2 = ($c >> 1) & 0x7fffffff;
if ($c & 1) $c = $z ^ ($c2); else $c = $c2;
}
$crc_table[$n] = $c;
}
// PNG file signature
$result = pack("c*", 137,80,78,71,13,10,26,10);
// IHDR chunk data:
//   width:              4 bytes
//   height:             4 bytes
//   bit depth:          1 byte (8 bits per RGB value)
//   color type:         1 byte (2 = RGB)
//   compression method: 1 byte (0 = deflate/inflate)
//   filter method:      1 byte (0 = adaptive filtering)
//   interlace method:   1 byte (0 = no interlace)
$data = pack("c*", ($sx >> 24) & 255,
($sx >> 16) & 255,
($sx >> 8) & 255,
$sx & 255,
($sy >> 24) & 255,
($sy >> 16) & 255,
($sy >> 8) & 255,
$sy & 255,
8,
2,
0,
0,
0);
add_chunk("IHDR");

// 以下不敢乱翻译,请自行参考 
//    scanline: 
//        filter byte: 0 = none 
//        RGB bytes for the line 
//    the scanline is compressed with "zlib", method 8 (RFC-1950): 
//        compression method/flags code: 1 byte ($78 = method 8, 32k window) 
//        additional flags/check bits:   1 byte ($01: FCHECK = 1, FDICT = 0, FLEVEL = 0) 
//        compressed data blocks:        n bytes 
//            one block (RFC-1951): 
//                bit 0: BFINAL: 1 for the last block 
//                bit 1 and 2: BTYPE: 0 for no compression 
//                next 2 bytes: LEN (LSB first) 
//                next 2 bytes: one's complement of LEN 
//                LEN bytes uncompressed data 
//        check value:  4 bytes (Adler-32 checksum of the uncompressed data)
//
$len = ($sx * 3 + 1) * $sy;
$data = pack("c*", 0x78, 0x01,
1,
$len & 255,
($len >> 8) & 255,
255 - ($len & 255),
255 - (($len >> 8) & 255));
$start = strlen($data);
$i2 = 0;
for ($h = 0; $h < $sy; $h++) {
$data .= chr(0);
for ($w = 0; $w < $sx * 3; $w++) {
$data .= $pixels[$i2++];
}
}
// calculate a Adler32 checksum with the bytes data[start..len-1]
$s1 = 1;
$s2 = 0;
for ($n = $start; $n < strlen($data); $n++) {
$s1 = ($s1 + ord($data[$n])) % 65521;
$s2 = ($s2 + $s1) % 65521;
}
$adler = ($s2 << 16) | $s1;
$data .= chr(($adler >> 24) & 255);
$data .= chr(($adler >> 16) & 255);
$data .= chr(($adler >> 8) & 255);
$data .= chr($adler & 255);
add_chunk("IDAT");
// IEND: marks the end of the PNG-file
$data = "";
add_chunk("IEND");
// 列印图象
echo($result);
?>

#6


楼上的好像不能用哦。

#7


$js没有定义,JS是什么呀?

#8


我做了10多年图片,当然知道这个,但是你要知道,差一个byte就是区别,而且不要忘了,那个是robot,不是人手,一次错了可以自动试几次,如果图片太少,很容易就破了

#9


一次错了!下一次的图片验证码就变了!它怎么试呢?
这个验证码每提交一次就改变一次!如何让能够让robot试几次呀?
老大!你说是吗?

#10


再说了,人家根据图片的文件名不是一样判断?

#11


:< 怎么能知道图片的文件名呢?

#12


robot 都能够自动填表,还不能读你的源码吗?

#13


哦我明白了,是看不到图片的文件名.
其实我认为,还有一个方法:
建立 0-9 这十个文件夹,0 的文件夹里放数字 0 ,1 的文件夹里放数字 1 的图片,可以放多幅不同的.依此类推.
然后随机生成一个 4 位数的验证码,保存在 $_SESSION[validate] 中.

输出源码:
<IMG SRC="{filepath}/validate_image.php?p=0"><IMG SRC="{filepath}/validate_image.php?p=1"><IMG SRC="{filepath}/validate_image.php?p=2"><IMG SRC="{filepath}/validate_image.php?p=3">

validate_image.php?p=i 根据 $_SESSION[validate] 读出第 $_GET[p] 位数字到 $n 中,再随机从 $n 目录中读出一幅输出来.

#14


下面就关于图片的字节数问题发表一下看法.
请先看一下下面的一篇文章:
《用COPY命令加密文本文件小技巧》
http://tech.tom.com/1380/1383/200399-58598.html
从这时里可以知道,可以在图片的源码在后面写入一些文字,但图片的显示却正常,但文件的大小已经改变了。
因此,我们可以通过这个方法,输出字节数完全相同的图片。
请各位牛人发表一下自己的看法。

#15


我的意思是说,你不可能做到几百张图片大部分都有相同的byte,即使验证码变换,出现不同的byte 的情况就有相对大的可能,robot这个验证码试不过去,就可以换另一个,只要有迹可寻……

gd产生的验证码目的就是把这种痕迹抹杀

为什么现在的gd验证码甚至做到变形,改变字符位置,这就是因为自动的OCR robot已经出现,判断字节数已经是过时了,我觉得,能够做“中文验证码”(我的意思是对不同语言使用者用不同字符)就是更高的途径,哈哈

#16


GD+SESSION
既然有GD库可以用,又安全,干吗要大费周章呢?
APACHE 4.0 以上
extension gd2.dll.dz;

#17


keaizhong(可爱钟):我天天在用,怎会不可以用,要不我贴个唠叨的原始代码给你们

参考这个:
不用GD库生成当前时间的PNG格式图象的程序  
该程序是不用GD库可以生成当前时间的PNG格式图象,给人大开眼界,很有参考价值. 

<?php 
        
    function set_4pixel($r, $g, $b, $x, $y) 
    { 
    global $sx, $sy, $pixels; 

    $ofs = 3 * ($sx * $y + $x); 
    $pixels[$ofs] = chr($r); 
    $pixels[$ofs + 1] = chr($g); 
    $pixels[$ofs + 2] = chr($b); 
    $pixels[$ofs + 3] = chr($r); 
    $pixels[$ofs + 4] = chr($g); 
    $pixels[$ofs + 5] = chr($b); 
    $ofs += 3 * $sx; 
    $pixels[$ofs] = chr($r); 
    $pixels[$ofs + 1] = chr($g); 
    $pixels[$ofs + 2] = chr($b); 
    $pixels[$ofs + 3] = chr($r); 
    $pixels[$ofs + 4] = chr($g); 
    $pixels[$ofs + 5] = chr($b); 
    } 
    //生成数字图象的函数     
    function draw2digits($x, $y, $number) 
    { 
    draw_digit($x, $y, (int) ($number / 10)); 
    draw_digit($x + 11, $y, $number % 10); 
    } 
         
    function draw_digit($x, $y, $digit) 
    { 
    global $sx, $sy, $pixels, $digits, $lines; 
             
    $digit = $digits[$digit]; 
    $m = 8; 
    for ($b = 1, $i = 0; $i < 7; $i++, $b *= 2) { 
        if (($b & $digit) == $b) { 
        $j = $i * 4; 
        $x0 = $lines[$j] * $m + $x; 
        $y0 = $lines[$j + 1] * $m + $y; 
        $x1 = $lines[$j + 2] * $m + $x; 
        $y1 = $lines[$j + 3] * $m + $y; 
        if ($x0 == $x1) { 
            $ofs = 3 * ($sx * $y0 + $x0); 
            for ($h = $y0; $h <= $y1; $h++, $ofs += 3 * $sx) { 
            $pixels[$ofs] = chr(0); 
            $pixels[$ofs + 1] = chr(0); 
            $pixels[$ofs + 2] = chr(0); 
            } 
        } else { 
            $ofs = 3 * ($sx * $y0 + $x0); 
            for ($w = $x0; $w <= $x1; $w++) { 
            $pixels[$ofs++] = chr(0); 
            $pixels[$ofs++] = chr(0); 
            $pixels[$ofs++] = chr(0); 
            } 
        } 
        } 
    } 
    } 
         
    //将文字加入到图象中  
    function add_chunk($type) 
    { 
    global $result, $data, $chunk, $crc_table; 

    // chunk :为层 
    // length: 4 字节: 用来计算 chunk  
    // chunk type: 4 字节 
    // chunk data: length bytes 
    // CRC: 4 字节:  循环冗余码校验 
         
    // copy data and create CRC checksum 
    $len = strlen($data); 
    $chunk = pack("c*", ($len >> 24) & 255, 
        ($len >> 16) & 255, 
        ($len >> 8) & 255, 
        $len & 255); 
    $chunk .= $type; 
    $chunk .= $data; 

    // calculate a CRC checksum with the bytes chunk[4..len-1] 
    $z = 16777215; 
    $z |= 255 << 24; 
    $c = $z; 
    for ($n = 4; $n < strlen($chunk); $n++) { 
        $c8 = ($c >> 8) & 0xffffff; 
        $c = $crc_table[($c ^ ord($chunk][$n])) & 0xff] ^ $c8; 
    } 
    $crc = $c ^ $z; 

    $chunk .= chr(($crc >> 24) & 255); 
    $chunk .= chr(($crc >> 16) & 255); 
    $chunk .= chr(($crc >> 8) & 255); 
    $chunk .= chr($crc & 255); 

    // 将结果加到$result中 
    $result .= $chunk; 
    } 


    //主程序 

    $sx = 80; 
    $sy = 21; 
    $pixels = ""; 
             
    // 填充 
    for ($h = 0; $h < $sy; $h++) { 
    for ($w = 0; $w < $sx; $w++) { 
        $r = 100 / $sx * $w + 155; 
        $g = 100 / $sy * $h + 155; 
        $b = 255 - (100 / ($sx + $sy) * ($w + $h)); 
        $pixels .= chr($r); 
        $pixels .= chr($g); 
        $pixels .= chr($b); 
    } 
    } 
         
    $date = getdate(); 
    $s = $date["seconds"]; 
    $m = $date["minutes"]; 
    $h = $date["hours"]; 
    $digits = array(95, 5, 118, 117, 45, 121, 123, 69, 127, 125); 
    $lines = array(1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 1, 2, 0, 1, 1, 1, 0, 0, 1, 0); 
         
    draw2digits(4, 2, $h); 
    draw2digits(30, 2, $m); 
    draw2digits(56, 2, $s); 
    set_4pixel(0, 0, 0, 26, 7); 
    set_4pixel(0, 0, 0, 26, 13); 
    set_4pixel(0, 0, 0, 52, 7); 
    set_4pixel(0, 0, 0, 52, 13); 

    // 创建循环冗余码校验表 
    $z = -306674912;  // = 0xedb88320 
    for ($n = 0; $n < 256; $n++) { 
        $c = $n; 
        for ($k = 0; $k < 8; $k++) { 
            $c2 = ($c >> 1) & 0x7fffffff; 
            if ($c & 1) $c = $z ^ ($c2); else $c = $c2; 
        } 
        $crc_table[$n] = $c; 
    } 

    // PNG file signature 
    $result = pack("c*", 137,80,78,71,13,10,26,10); 
         
    // IHDR chunk data: 
    //   width:              4 bytes 
    //   height:             4 bytes 
    //   bit depth:          1 byte (8 bits per RGB value) 
    //   color type:         1 byte (2 = RGB) 
    //   compression method: 1 byte (0 = deflate/inflate) 
    //   filter method:      1 byte (0 = adaptive filtering) 
    //   interlace method:   1 byte (0 = no interlace) 
    $data = pack("c*", ($sx >> 24) & 255, 
    ($sx >> 16) & 255, 
    ($sx >> 8) & 255, 
    $sx & 255, 
    ($sy >> 24) & 255, 
    ($sy >> 16) & 255, 
    ($sy >> 8) & 255, 
    $sy & 255, 
    8, 
    2, 
    0, 
    0, 
    0); 
    add_chunk("IHDR"); 

    // 以下不敢乱翻译,请自行参考 
    //    scanline: 
    //        filter byte: 0 = none 
    //        RGB bytes for the line 
    //    the scanline is compressed with "zlib", method 8 (RFC-1950): 
    //        compression method/flags code: 1 byte ($78 = method 8, 32k window) 
    //        additional flags/check bits:   1 byte ($01: FCHECK = 1, FDICT = 0, FLEVEL = 0) 
    //        compressed data blocks:        n bytes 
    //            one block (RFC-1951): 
    //                bit 0: BFINAL: 1 for the last block 
    //                bit 1 and 2: BTYPE: 0 for no compression 
    //                next 2 bytes: LEN (LSB first) 
    //                next 2 bytes: one's complement of LEN 
    //                LEN bytes uncompressed data 
    //        check value:  4 bytes (Adler-32 checksum of the uncompressed data) 
    // 
    $len = ($sx * 3 + 1) * $sy; 
    $data = pack("c*", 0x78, 0x01, 
        1, 
    $len & 255, 
    ($len >> 8) & 255, 
    255 - ($len & 255), 
    255 - (($len >> 8) & 255)); 
    $start = strlen($data); 
    $i2 = 0; 
    for ($h = 0; $h < $sy; $h++) { 
    $data .= chr(0); 
    for ($w = 0; $w < $sx * 3; $w++) { 
        $data .= $pixels[$i2++]; 
    } 
    } 


    // calculate a Adler32 checksum with the bytes data[start..len-1] 
    $s1 = 1; 
    $s2 = 0; 
    for ($n = $start; $n < strlen($data); $n++) { 
    $s1 = ($s1 + ord($data[$n])) % 65521; 
    $s2 = ($s2 + $s1) % 65521; 
    } 
    $adler = ($s2 << 16) | $s1; 

    $data .= chr(($adler >> 24) & 255); 
    $data .= chr(($adler >> 16) & 255); 
    $data .= chr(($adler >> 8) & 255); 
    $data .= chr($adler & 255); 
    add_chunk("IDAT"); 

    // IEND: marks the end of the PNG-file 
    $data = ""; 
    add_chunk("IEND"); 

    // 列印图象 
     
    echo($result); 
?> 

//如何调用,其实很简单,将上面存为Timeimg.php 
//然后新建一个页面如下: 

<html> 
    <head> 
    <title>test</title> 
    <meta http-equiv="Content-Type" content="text/html"> 
    </head> 
    <body> 
    <img src="Timeimg.php">  //以图象连接方式调用PHP文件 
</body> 
</html>

#1


多做一些图片效果更好一些!不容易重复!

#2


验证码的目的就是要阻止客户端robot的使用,除非你预设的图片足够多
否则客户端可以通过捕获图片的字节数实现自动获取验证码

#3


snmr_com(麒麟厍人)其实你用FireWork做一些图片你就能看出来!
同样大小的图片,如果只是数字不一样的话!大小几乎都是差不多的!
都是那几个字节,呵呵,几百张图片,几乎都是一样的!所以robot应该是弄不出来!

#4


呵呵,没用GD库,这样也确实是个解决办法.

#5


我在没有GD库的情况,是这样用的,以下代码感谢唠叨提供一个显示时间的程序,我从这个修改过来的,现在可以显示4位数字随机图片。

<?php
//生成数字图象的函数
function draw_digit($x, $y, $digit)
{
global $sx, $sy, $pixels, $digits, $lines;
$digit = $digits[$digit];
$m = 8;
for ($b = 1, $i = 0; $i < 7; $i++, $b *= 2) {
if (($b & $digit) == $b) {
$j = $i * 4;
$x0 = $lines[$j] * $m + $x;
$y0 = $lines[$j + 1] * $m + $y;
$x1 = $lines[$j + 2] * $m + $x;
$y1 = $lines[$j + 3] * $m + $y;
if ($x0 == $x1) {
$ofs = 3 * ($sx * $y0 + $x0);
for ($h = $y0; $h <= $y1; $h++, $ofs += 3 * $sx) {
$pixels[$ofs] = chr(0);
$pixels[$ofs + 1] = chr(0);
$pixels[$ofs + 2] = chr(0);
}
} else {
$ofs = 3 * ($sx * $y0 + $x0);
for ($w = $x0; $w <= $x1; $w++) {
$pixels[$ofs++] = chr(0);
$pixels[$ofs++] = chr(0);
$pixels[$ofs++] = chr(0);
}
}
}
}
}
//将文字加入到图象中
function add_chunk($type)
{
global $result, $data, $chunk, $crc_table;
// chunk :为层
// length: 4 字节: 用来计算 chunk
// chunk type: 4 字节
// chunk data: length bytes
// CRC: 4 字节:  循环冗余码校验
// copy data and create CRC checksum
$len = strlen($data);
$chunk = pack("c*", ($len >> 24) & 255,
($len >> 16) & 255,
($len >> 8) & 255,
$len & 255);
$chunk .= $type;
$chunk .= $data;
// calculate a CRC checksum with the bytes chunk[4..len-1]
$z = 16777215;
$z |= 255 << 24;
$c = $z;
for ($n = 4; $n < strlen($chunk); $n++) {
$c8 = ($c >> 8) & 0xffffff;
$c = $crc_table[($c ^ ord($chunk[$n])) & 0xff] ^ $c8;
}
$crc = $c ^ $z;
$chunk .= chr(($crc >> 24) & 255);
$chunk .= chr(($crc >> 16) & 255);
$chunk .= chr(($crc >> 8) & 255);
$chunk .= chr($crc & 255);
// 将结果加到$result中
$result .= $chunk;
}
//主程序
//$sx = 80;
$sx = strlen($sj)*13+2;
$sy = 21;
$pixels = "";
// 填充
for ($h = 0; $h < $sy; $h++) {
for ($w = 0; $w < $sx; $w++) {
$r = 100 / $sx * $w + 155;
$g = 100 / $sy * $h + 155;
$b = 255 - (100 / ($sx + $sy) * ($w + $h));
$pixels .= chr($r);
$pixels .= chr($g);
$pixels .= chr($b);
}
}
$digits = array(95, 5, 118, 117, 45, 121, 123, 69, 127, 125);
$lines = array(1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 1, 2, 0, 1, 1, 1, 0, 0, 1, 0);
function draw($str){
$k = 3;
for($j=0; $j<strlen($str); $j++) {
draw_digit($k, 2, $str[$j]);
$k+=13;
}
}
draw($sj);
// 创建循环冗余码校验表
$z = -306674912;  // = 0xedb88320
for ($n = 0; $n < 256; $n++) {
$c = $n;
for ($k = 0; $k < 8; $k++) {
$c2 = ($c >> 1) & 0x7fffffff;
if ($c & 1) $c = $z ^ ($c2); else $c = $c2;
}
$crc_table[$n] = $c;
}
// PNG file signature
$result = pack("c*", 137,80,78,71,13,10,26,10);
// IHDR chunk data:
//   width:              4 bytes
//   height:             4 bytes
//   bit depth:          1 byte (8 bits per RGB value)
//   color type:         1 byte (2 = RGB)
//   compression method: 1 byte (0 = deflate/inflate)
//   filter method:      1 byte (0 = adaptive filtering)
//   interlace method:   1 byte (0 = no interlace)
$data = pack("c*", ($sx >> 24) & 255,
($sx >> 16) & 255,
($sx >> 8) & 255,
$sx & 255,
($sy >> 24) & 255,
($sy >> 16) & 255,
($sy >> 8) & 255,
$sy & 255,
8,
2,
0,
0,
0);
add_chunk("IHDR");

// 以下不敢乱翻译,请自行参考 
//    scanline: 
//        filter byte: 0 = none 
//        RGB bytes for the line 
//    the scanline is compressed with "zlib", method 8 (RFC-1950): 
//        compression method/flags code: 1 byte ($78 = method 8, 32k window) 
//        additional flags/check bits:   1 byte ($01: FCHECK = 1, FDICT = 0, FLEVEL = 0) 
//        compressed data blocks:        n bytes 
//            one block (RFC-1951): 
//                bit 0: BFINAL: 1 for the last block 
//                bit 1 and 2: BTYPE: 0 for no compression 
//                next 2 bytes: LEN (LSB first) 
//                next 2 bytes: one's complement of LEN 
//                LEN bytes uncompressed data 
//        check value:  4 bytes (Adler-32 checksum of the uncompressed data)
//
$len = ($sx * 3 + 1) * $sy;
$data = pack("c*", 0x78, 0x01,
1,
$len & 255,
($len >> 8) & 255,
255 - ($len & 255),
255 - (($len >> 8) & 255));
$start = strlen($data);
$i2 = 0;
for ($h = 0; $h < $sy; $h++) {
$data .= chr(0);
for ($w = 0; $w < $sx * 3; $w++) {
$data .= $pixels[$i2++];
}
}
// calculate a Adler32 checksum with the bytes data[start..len-1]
$s1 = 1;
$s2 = 0;
for ($n = $start; $n < strlen($data); $n++) {
$s1 = ($s1 + ord($data[$n])) % 65521;
$s2 = ($s2 + $s1) % 65521;
}
$adler = ($s2 << 16) | $s1;
$data .= chr(($adler >> 24) & 255);
$data .= chr(($adler >> 16) & 255);
$data .= chr(($adler >> 8) & 255);
$data .= chr($adler & 255);
add_chunk("IDAT");
// IEND: marks the end of the PNG-file
$data = "";
add_chunk("IEND");
// 列印图象
echo($result);
?>

#6


楼上的好像不能用哦。

#7


$js没有定义,JS是什么呀?

#8


我做了10多年图片,当然知道这个,但是你要知道,差一个byte就是区别,而且不要忘了,那个是robot,不是人手,一次错了可以自动试几次,如果图片太少,很容易就破了

#9


一次错了!下一次的图片验证码就变了!它怎么试呢?
这个验证码每提交一次就改变一次!如何让能够让robot试几次呀?
老大!你说是吗?

#10


再说了,人家根据图片的文件名不是一样判断?

#11


:< 怎么能知道图片的文件名呢?

#12


robot 都能够自动填表,还不能读你的源码吗?

#13


哦我明白了,是看不到图片的文件名.
其实我认为,还有一个方法:
建立 0-9 这十个文件夹,0 的文件夹里放数字 0 ,1 的文件夹里放数字 1 的图片,可以放多幅不同的.依此类推.
然后随机生成一个 4 位数的验证码,保存在 $_SESSION[validate] 中.

输出源码:
<IMG SRC="{filepath}/validate_image.php?p=0"><IMG SRC="{filepath}/validate_image.php?p=1"><IMG SRC="{filepath}/validate_image.php?p=2"><IMG SRC="{filepath}/validate_image.php?p=3">

validate_image.php?p=i 根据 $_SESSION[validate] 读出第 $_GET[p] 位数字到 $n 中,再随机从 $n 目录中读出一幅输出来.

#14


下面就关于图片的字节数问题发表一下看法.
请先看一下下面的一篇文章:
《用COPY命令加密文本文件小技巧》
http://tech.tom.com/1380/1383/200399-58598.html
从这时里可以知道,可以在图片的源码在后面写入一些文字,但图片的显示却正常,但文件的大小已经改变了。
因此,我们可以通过这个方法,输出字节数完全相同的图片。
请各位牛人发表一下自己的看法。

#15


我的意思是说,你不可能做到几百张图片大部分都有相同的byte,即使验证码变换,出现不同的byte 的情况就有相对大的可能,robot这个验证码试不过去,就可以换另一个,只要有迹可寻……

gd产生的验证码目的就是把这种痕迹抹杀

为什么现在的gd验证码甚至做到变形,改变字符位置,这就是因为自动的OCR robot已经出现,判断字节数已经是过时了,我觉得,能够做“中文验证码”(我的意思是对不同语言使用者用不同字符)就是更高的途径,哈哈

#16


GD+SESSION
既然有GD库可以用,又安全,干吗要大费周章呢?
APACHE 4.0 以上
extension gd2.dll.dz;

#17


keaizhong(可爱钟):我天天在用,怎会不可以用,要不我贴个唠叨的原始代码给你们

参考这个:
不用GD库生成当前时间的PNG格式图象的程序  
该程序是不用GD库可以生成当前时间的PNG格式图象,给人大开眼界,很有参考价值. 

<?php 
        
    function set_4pixel($r, $g, $b, $x, $y) 
    { 
    global $sx, $sy, $pixels; 

    $ofs = 3 * ($sx * $y + $x); 
    $pixels[$ofs] = chr($r); 
    $pixels[$ofs + 1] = chr($g); 
    $pixels[$ofs + 2] = chr($b); 
    $pixels[$ofs + 3] = chr($r); 
    $pixels[$ofs + 4] = chr($g); 
    $pixels[$ofs + 5] = chr($b); 
    $ofs += 3 * $sx; 
    $pixels[$ofs] = chr($r); 
    $pixels[$ofs + 1] = chr($g); 
    $pixels[$ofs + 2] = chr($b); 
    $pixels[$ofs + 3] = chr($r); 
    $pixels[$ofs + 4] = chr($g); 
    $pixels[$ofs + 5] = chr($b); 
    } 
    //生成数字图象的函数     
    function draw2digits($x, $y, $number) 
    { 
    draw_digit($x, $y, (int) ($number / 10)); 
    draw_digit($x + 11, $y, $number % 10); 
    } 
         
    function draw_digit($x, $y, $digit) 
    { 
    global $sx, $sy, $pixels, $digits, $lines; 
             
    $digit = $digits[$digit]; 
    $m = 8; 
    for ($b = 1, $i = 0; $i < 7; $i++, $b *= 2) { 
        if (($b & $digit) == $b) { 
        $j = $i * 4; 
        $x0 = $lines[$j] * $m + $x; 
        $y0 = $lines[$j + 1] * $m + $y; 
        $x1 = $lines[$j + 2] * $m + $x; 
        $y1 = $lines[$j + 3] * $m + $y; 
        if ($x0 == $x1) { 
            $ofs = 3 * ($sx * $y0 + $x0); 
            for ($h = $y0; $h <= $y1; $h++, $ofs += 3 * $sx) { 
            $pixels[$ofs] = chr(0); 
            $pixels[$ofs + 1] = chr(0); 
            $pixels[$ofs + 2] = chr(0); 
            } 
        } else { 
            $ofs = 3 * ($sx * $y0 + $x0); 
            for ($w = $x0; $w <= $x1; $w++) { 
            $pixels[$ofs++] = chr(0); 
            $pixels[$ofs++] = chr(0); 
            $pixels[$ofs++] = chr(0); 
            } 
        } 
        } 
    } 
    } 
         
    //将文字加入到图象中  
    function add_chunk($type) 
    { 
    global $result, $data, $chunk, $crc_table; 

    // chunk :为层 
    // length: 4 字节: 用来计算 chunk  
    // chunk type: 4 字节 
    // chunk data: length bytes 
    // CRC: 4 字节:  循环冗余码校验 
         
    // copy data and create CRC checksum 
    $len = strlen($data); 
    $chunk = pack("c*", ($len >> 24) & 255, 
        ($len >> 16) & 255, 
        ($len >> 8) & 255, 
        $len & 255); 
    $chunk .= $type; 
    $chunk .= $data; 

    // calculate a CRC checksum with the bytes chunk[4..len-1] 
    $z = 16777215; 
    $z |= 255 << 24; 
    $c = $z; 
    for ($n = 4; $n < strlen($chunk); $n++) { 
        $c8 = ($c >> 8) & 0xffffff; 
        $c = $crc_table[($c ^ ord($chunk][$n])) & 0xff] ^ $c8; 
    } 
    $crc = $c ^ $z; 

    $chunk .= chr(($crc >> 24) & 255); 
    $chunk .= chr(($crc >> 16) & 255); 
    $chunk .= chr(($crc >> 8) & 255); 
    $chunk .= chr($crc & 255); 

    // 将结果加到$result中 
    $result .= $chunk; 
    } 


    //主程序 

    $sx = 80; 
    $sy = 21; 
    $pixels = ""; 
             
    // 填充 
    for ($h = 0; $h < $sy; $h++) { 
    for ($w = 0; $w < $sx; $w++) { 
        $r = 100 / $sx * $w + 155; 
        $g = 100 / $sy * $h + 155; 
        $b = 255 - (100 / ($sx + $sy) * ($w + $h)); 
        $pixels .= chr($r); 
        $pixels .= chr($g); 
        $pixels .= chr($b); 
    } 
    } 
         
    $date = getdate(); 
    $s = $date["seconds"]; 
    $m = $date["minutes"]; 
    $h = $date["hours"]; 
    $digits = array(95, 5, 118, 117, 45, 121, 123, 69, 127, 125); 
    $lines = array(1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 1, 2, 0, 1, 1, 1, 0, 0, 1, 0); 
         
    draw2digits(4, 2, $h); 
    draw2digits(30, 2, $m); 
    draw2digits(56, 2, $s); 
    set_4pixel(0, 0, 0, 26, 7); 
    set_4pixel(0, 0, 0, 26, 13); 
    set_4pixel(0, 0, 0, 52, 7); 
    set_4pixel(0, 0, 0, 52, 13); 

    // 创建循环冗余码校验表 
    $z = -306674912;  // = 0xedb88320 
    for ($n = 0; $n < 256; $n++) { 
        $c = $n; 
        for ($k = 0; $k < 8; $k++) { 
            $c2 = ($c >> 1) & 0x7fffffff; 
            if ($c & 1) $c = $z ^ ($c2); else $c = $c2; 
        } 
        $crc_table[$n] = $c; 
    } 

    // PNG file signature 
    $result = pack("c*", 137,80,78,71,13,10,26,10); 
         
    // IHDR chunk data: 
    //   width:              4 bytes 
    //   height:             4 bytes 
    //   bit depth:          1 byte (8 bits per RGB value) 
    //   color type:         1 byte (2 = RGB) 
    //   compression method: 1 byte (0 = deflate/inflate) 
    //   filter method:      1 byte (0 = adaptive filtering) 
    //   interlace method:   1 byte (0 = no interlace) 
    $data = pack("c*", ($sx >> 24) & 255, 
    ($sx >> 16) & 255, 
    ($sx >> 8) & 255, 
    $sx & 255, 
    ($sy >> 24) & 255, 
    ($sy >> 16) & 255, 
    ($sy >> 8) & 255, 
    $sy & 255, 
    8, 
    2, 
    0, 
    0, 
    0); 
    add_chunk("IHDR"); 

    // 以下不敢乱翻译,请自行参考 
    //    scanline: 
    //        filter byte: 0 = none 
    //        RGB bytes for the line 
    //    the scanline is compressed with "zlib", method 8 (RFC-1950): 
    //        compression method/flags code: 1 byte ($78 = method 8, 32k window) 
    //        additional flags/check bits:   1 byte ($01: FCHECK = 1, FDICT = 0, FLEVEL = 0) 
    //        compressed data blocks:        n bytes 
    //            one block (RFC-1951): 
    //                bit 0: BFINAL: 1 for the last block 
    //                bit 1 and 2: BTYPE: 0 for no compression 
    //                next 2 bytes: LEN (LSB first) 
    //                next 2 bytes: one's complement of LEN 
    //                LEN bytes uncompressed data 
    //        check value:  4 bytes (Adler-32 checksum of the uncompressed data) 
    // 
    $len = ($sx * 3 + 1) * $sy; 
    $data = pack("c*", 0x78, 0x01, 
        1, 
    $len & 255, 
    ($len >> 8) & 255, 
    255 - ($len & 255), 
    255 - (($len >> 8) & 255)); 
    $start = strlen($data); 
    $i2 = 0; 
    for ($h = 0; $h < $sy; $h++) { 
    $data .= chr(0); 
    for ($w = 0; $w < $sx * 3; $w++) { 
        $data .= $pixels[$i2++]; 
    } 
    } 


    // calculate a Adler32 checksum with the bytes data[start..len-1] 
    $s1 = 1; 
    $s2 = 0; 
    for ($n = $start; $n < strlen($data); $n++) { 
    $s1 = ($s1 + ord($data[$n])) % 65521; 
    $s2 = ($s2 + $s1) % 65521; 
    } 
    $adler = ($s2 << 16) | $s1; 

    $data .= chr(($adler >> 24) & 255); 
    $data .= chr(($adler >> 16) & 255); 
    $data .= chr(($adler >> 8) & 255); 
    $data .= chr($adler & 255); 
    add_chunk("IDAT"); 

    // IEND: marks the end of the PNG-file 
    $data = ""; 
    add_chunk("IEND"); 

    // 列印图象 
     
    echo($result); 
?> 

//如何调用,其实很简单,将上面存为Timeimg.php 
//然后新建一个页面如下: 

<html> 
    <head> 
    <title>test</title> 
    <meta http-equiv="Content-Type" content="text/html"> 
    </head> 
    <body> 
    <img src="Timeimg.php">  //以图象连接方式调用PHP文件 
</body> 
</html>