背景图片的文件名
* 1 => red, 2 => green, 3 => blue
* @var array $themes
*/
var $themes_jpg = array(
1 => array('captcha_bg1.jpg', 255, 255, 255),
2 => array('captcha_bg2.jpg', 0, 0, 0),
3 => array('captcha_bg3.jpg', 0, 0, 0),
4 => array('captcha_bg4.jpg', 255, 255, 255),
5 => array('captcha_bg5.jpg', 255, 255, 255),
);
var $themes_gif = array(
1 => array('captcha_bg1.gif', 255, 255, 255),
2 => array('captcha_bg2.gif', 0, 0, 0),
3 => array('captcha_bg3.gif', 0, 0, 0),
4 => array('captcha_bg4.gif', 255, 255, 255),
5 => array('captcha_bg5.gif', 255, 255, 255),
);
/**
* 图片的宽度
*
* @var integer $width
*/
var $width = 38;
/**
* 图片的高度
*
* @var integer $height
*/
var $height = 16;
/**
* 构造函数
*
* @access public
* @param
*
* @return void
*/
function __construct($folder = '', $width = 38, $height = 16)
{
$this->captcha($folder, $width, $height);
}
/**
* 构造函数
*
* @access public
* @param string $folder 背景图片所在目录
* @param integer $width 图片宽度
* @param integer $height 图片高度
* @return bool
*/
function captcha($folder = '', $width = 38, $height = 16)
{
$folder = root_path . 'includes/captcha/';
if (!empty($folder))
{
$this->folder = $folder;
}
$this->width = $width;
$this->height = $height;
/* 检查是否支持 gd */
if (php_version >= '4.3')
{
return (function_exists('imagecreatetruecolor') || function_exists('imagecreate'));
}
else
{
return (((imagetypes() & img_gif) > 0) || ((imagetypes() & img_jpg)) > 0 );
}
}
/**
* 检查给出的验证码是否和session中的一致
*
* @access public
* @param string $word 验证码
* @return bool
*/
function check_word($word)
{
$recorded = isset($_session[$this->session_word]) ? base64_decode($_session[$this->session_word]) : '';
$given = $this->encrypts_word(strtoupper($word));
return (preg_match(/$given/, $recorded));
}
/**
* 生成图片并输出到浏览器
*
* @access public
* @param string $word 验证码
* @return mix
*/
function generate_image($word = false)
{
if (!$word)
{
$word = $this->generate_word();
}
/* 记录验证码到session */
$this->record_word($word);
/* 验证码长度 */
$letters = strlen($word);
/* 选择一个随机的方案 */
mt_srand((double) microtime() * 1000000);
if (function_exists('imagecreatefromjpeg') && ((imagetypes() & img_jpg) > 0))
{
$theme = $this->themes_jpg[mt_rand(1, count($this->themes_jpg))];
}
else
{
$theme = $this->themes_gif[mt_rand(1, count($this->themes_gif))];
}
if (!file_exists($this->folder . $theme[0]))
{
return false;
}
else
{
$img_bg = (function_exists('imagecreatefromjpeg') && ((imagetypes() & img_jpg) > 0)) ?
imagecreatefromjpeg($this->folder . $theme[0]) : imagecreatefromgif($this->folder . $theme[0]);
$bg_width = imagesx($img_bg);
$bg_height = imagesy($img_bg);
$img_org = ((function_exists('imagecreatetruecolor')) && php_version >= '4.3') ?
imagecreatetruecolor($this->width, $this->height) : imagecreate($this->width, $this->height);
/* 将背景图象复制原始图象并调整大小 */
if (function_exists('imagecopyresampled') && php_version >= '4.3') // gd 2.x
{
imagecopyresampled($img_org, $img_bg, 0, 0, 0, 0, $this->width, $this->height, $bg_width, $bg_height);
}
else // gd 1.x
{
imagecopyresized($img_org, $img_bg, 0, 0, 0, 0, $this->width, $this->height, $bg_width, $bg_height);
}
imagedestroy($img_bg);
$clr = imagecolorallocate($img_org, $theme[1], $theme[2], $theme[3]);
/* 绘制边框 */
//imagerectangle($img_org, 0, 0, $this->width - 1, $this->height - 1, $clr);
/* 获得验证码的高度和宽度 */
$x = ($this->width - (imagefontwidth(5) * $letters)) / 2;
$y = ($this->height - imagefontheight(5)) / 2;
imagestring($img_org, 5, $x, $y, $word, $clr);
header('expires: thu, 01 jan 1970 00:00:00 gmt');
// http/1.1
header('cache-control: private, no-store, no-cache, must-revalidate');
header('cache-control: post-check=0, pre-check=0, max-age=0', false);
// http/1.0
header('pragma: no-cache');
if ($this->img_type == 'jpeg' && function_exists('imagecreatefromjpeg'))
{
header('content-type: image/jpeg');
imageinterlace($img_org, 1);
imagejpeg($img_org, false, 95);
}
else
{
header('content-type: image/png');
imagepng($img_org);
}
imagedestroy($img_org);
return true;
}
}
/*------------------------------------------------------ */
//-- private methods
/*------------------------------------------------------ */
/**
* 对需要记录的串进行加密
*
* @access private
* @param string $word 原始字符串
* @return string
*/
function encrypts_word($word)
{
return substr(md5($word), 1, 10);
}
/**
* 将验证码保存到session
*
* @access private
* @param string $word 原始字符串
* @return void
*/
function record_word($word)
{
$_session[$this->session_word] = base64_encode($this->encrypts_word($word));
}
/**
* 生成随机的验证码
*
* @access private
* @param integer $length 验证码长度
* @return string
*/
function generate_word($length = 4)
{
$chars = '1234567890abcdefghjklmnpqrstuvwxyz';
for ($i = 0, $count = strlen($chars); $i {
$arr[$i] = $chars[$i];
}
mt_srand((double) microtime() * 1000000);
shuffle($arr);
return substr(implode('', $arr), 5, $length);
}
}
?>
回复讨论(解决方案) 只看到 check_word 的定义,没看到 check_word 的调用
也没看到 session_start
在提交页面里有调用的:
include_once('includes/cls_captcha.php');
$validator = new captcha();
if (!$validator->check_word($t_captcha))
{
$ajax['record']['all_tp'] = 9;
echo json_encode($ajax);
exit;
}
那 session_start(); 在哪里?
好像是没有,那怎么弄?
session_start(); 这个也有的,在另一个文件里
require(root_path . 'includes/init.php');每个页面都有这个文件,session_start(); 就在这个文件里
你传入的 验证码在哪里?怎么没传给 $validator
js:
function get_toupiao(tp_id,all_toupiao,hd_id,tp_star_time,tp_end_time)
{
if($.trim($(input[name=captcha]).val()) == '1')
{
if($.trim($(input[name=t_captcha]).val()) == '')
{
alert(验证码不能为空!);
$(input[name=t_captcha]).focus();
return false;
}
}
var t_captcha=$.trim($(input[name=t_captcha]).val());
var captcha=$.trim($(input[name=captcha]).val());
var originator=$.trim($(input[name=originator]).val());
$.get(/show.php?act=get_toupiao,{
tp_id:tp_id,
all_toupiao:all_toupiao,
hd_id:hd_id,
tp_star_time:tp_star_time,
tp_end_time:tp_end_time,
t_captcha:t_captcha,
captcha:captcha,
originator:originator,
async:false,
rand: math.random()
},function(data){
if(data.record.all_tp==9)
{
alert(验证码输入错误^_^!);
return false;
}
/*if(data.record.all_tp==8)
{
alert(请进行有效投票哦^_^!);
return false;
}
if(data.record.all_tp==7)
{
alert(同时投票的人太多,请稍候重试^_^!);
return false;
}*/
if(data.record.all_tp==5)
{
alert(今天您已经投票,请明天再投吧!);
return false;
}
if(data.record.all_tp==6)
{
alert(今天您已经投票,请明天再投吧!);
return false;
}
if(data.record.all_tp==3)
{
alert(投票时间已过,不能投票);
return false;
}
if(data.record.all_tp==4)
{
alert(投票时间还没到,不能投票);
return false;
}
if(data.record.all_tp==1)
{
alert(该活动您已投票,不能重复投票);
return false;
}
if(data.record.all_tp==2)
{
alert(该项目您已投票,不能重复投票);
return false;
}
if(data.status.code==1)
{
//成功
$(#tp_+tp_id+).empty();
$(#tp_+tp_id+).append(+data.record.tp_count+);
$(#captcha_+tp_id+).empty();
$(#captcha_+tp_id+).append(+data.status.captcha+);
alert(投票成功!);
return false;
}
},json);
}
php:
elseif($action == 'get_toupiao')
{
global $fdyu,$db;
$tp_id = intval($_get['tp_id']);
$hd_id = intval($_get['hd_id']);
$all_toupiao = $_get['all_toupiao'];
$tp_star_time = $_get['tp_star_time'];
$tp_end_time = $_get['tp_end_time'];
$t_captcha = $_get['t_captcha'];
$captcha = intval($_get['captcha']);
$ip=getclientip();
$ajax = array();
//是否需要验证码
if($captcha==1)
{
include_once('includes/cls_captcha.php');
$validator = new captcha();
if (!$validator->check_word($t_captcha))
{
$ajax['record']['all_tp'] = 9;
echo json_encode($ajax);
exit;
}
}
提供检查思路:
1.如果输入为空是否可以通过
2.把输入的验证码和session的验证码打印出来看看
3.验证通过后,需要把旧的验证码删除,否则用户可以不刷新页面,一直用这个验证码提交不同的数据
可以参考: http://blog.csdn.net/fdipzone/article/details/7295496
以前刷yii哥帖子时发现csdn就有楼上说的第3个bug,不过刷完转天他们就修复了
验证码防刷票是个很不靠谱的东西,如果投票数牵扯到利益,那用户完全可以去买付费的验证码识别
我觉得归根到底还是得ip去重
ip限了,但也没用,刷票软件可以刷不同的ip
10楼,我发现确实是像你说的第三点,因为我在数据库里记录了验证码,发现有重复的验证码!那怎么删除旧的验证码呢?
if($action == 'get_toupiao')
{
。。。。。。省略
if ($_session['code_1']!=$t_captcha)
{
$ajax['record']['all_tp'] = 9;
echo json_encode($ajax);
exit;
}
。。。。。省略
$ajax['status']['code'] = 1; //成功
echo json_encode($ajax);
exit;
}
是在$ajax['status']['code'] = 1; //成功这个上面加unset($_session['code_1']);这个吗?
就是通过验证后,把session的验证码清空就可以了。
保证令牌只能用一次