yz20sui 发表于 2008-9-22 20:55:59

验证码模型 For CodeIgniter

例子:

准备工作

在 system\application\models 下建立文件vcode_model.php
内容如下<?phpif ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* by frank
* qq 108818
**/

Class Vcode_model extends Model
{
public $width= 57; //宽度
public $height = 20; //高度
public $len    = 4;//字符长度
public $backcolor= '#FFFFFF' ;//背景色
public $bordercolor = null;   //边框色
public $noisenum= NULL ;//杂点数量

public $textsize = 10;    //字体大小
public $font = "04b_08.ttf" ;    //自定义字体
public $imagename ;
protected $image ;   //图片变量
protected $backcolorRGB ;//背景色RGB
protected $bordercolorRGB = null;   //边框色
protected $size;   //每个字符的宽度(px)
protected $sizestr2str;//字符间距
public $vcode= NULL; //验证码内容(数字)
function __construct()
{
parent::Model();


}
public function show_img()
{
header("Content-type: image/png");
//$this->imagename = 'vcode/'.md5(date("YmdHis").$this->vcode).'.png';
//imagePng($this->image,$this->imagename);
imagePng($this->image);
imagedestroy($this->image);
}

public function make_img()
{
$this->image = imageCreate($this->width, $this->height); //创建图片
$this->backcolorRGB = $this->getcolor($this->backcolor);   //将#ffffff格式的背景色转换成RGB格式
imageFilledRectangle($this->image, 0, 0, $this->width, $this->height, $this->backcolorRGB); //画一矩形 并填充
$this->size = $this->width/$this->len; //宽度除以字符数 = 每个字符需要的宽度
if($this->size>$this->height) $this->size=$this->height; //如果 每个字符需要的宽度 大于图片高度 则 单字符宽度=高度(正方块)
$this->sizestr2str = $this->size/10 ; //以每个字符的1/10宽度为 字符间距
$left = ($this->width-$this->len*($this->size+$this->sizestr2str))/$this->size;   // (验证码图片宽度 - 实际需要的宽度)/每个字符的宽度 = 距离左边的宽度
for ($i=0; $i<$this->len; $i++)
{
   $randtext = rand(0, 9);//验证码数字 0-9随机数
   $this->vcode .= $randtext; //写入session的数字
   $textColor = imageColorAllocate($this->image, rand(50, 155), rand(50, 155), rand(50, 155)); //图片文字颜色
   if (!isset($this->textsize) ) $this->textsize = rand( ($this->size-$this->size/10), ($this->size + $this->size/10) ); //如果未定义字体大小 则取随机大小
   $location = $left + ($i*$this->size+$this->size/10);
   imagettftext($this->image, $this->textsize, rand(-18,18), $location, rand($this->size-$this->size/10, $this->size+$this->size/10), $textColor, $this->font, $randtext); //生成单个字体图象
}
if( isset($this->noisenum)) $this->setnoise(); //杂点处理
$_SESSION['vcode'] = $this->vcode; //写入session

if(isset($this->bordercolor)) //边框处理
{
   $this->bordercolorRGB = $this->getcolor($this->bordercolor);
   imageRectangle($this->image, 0, 0, $this->width-1, $this->height-1, $this->bordercolorRGB);
}

}

protected function getcolor($color)
{
$color = eregi_replace ("^#","",$color);
$r = $color.$color;
$r = hexdec ($r);
$b = $color.$color;
$b = hexdec ($b);
$g = $color.$color;
$g = hexdec ($g);
$color = imagecolorallocate ($this->image, $r, $b, $g);
return $color;
}
protected function setnoise()
{
for ($i=0; $i<$this->noisenum; $i++)
{
   $randColor = imageColorAllocate($this->image, rand(0, 255), rand(0, 255), rand(0, 255));
   imageSetPixel($this->image, rand(0, $this->width), rand(0, $this->height), $randColor);
}
}
}在 system\application\controllers 下建立 文件 vcode.php

内容如下
<?php
/**
* by frank
* qq 108818
**/
class Index extends Controller {
function __construct()
{
parent::Controller();
$this->load->helper('url');
$this->load->library('session');
$this->vcodeimg();

function vcodeimg()
{
/***验证码**/
$this->load->model('vcode_model');
$this->vcode_model->make_img();
$this->session->set_userdata('vcode', $this->vcode_model->vcode);
$this->vcode_model->show_img();
}

function showsession()    //这个方法可以删除 仅供debug
{
   echo '<pre>';
   var_dump($this->session->userdata);
   echo '</pre>';
}

}然后将打开

http://127.0.0.1/index.php/vcode/

看看能否正确看到验证码

需要查看 当前session中保存的数据 访问这个页面
http://127.0.0.1/index.php/vcode/showsession数组中 vcode 下面的4位 阿拉伯数字 即为验证码


如果想要在某个页面显示验证码图片
需要 在该页面所对应的视图中 增加如下代码片段
function $(objectId)
{
if(document.getElementById && document.getElementById(objectId))
{
   // W3C DOM
   return document.getElementById(objectId);
}
else if (document.all && document.all(objectId))
{
   // MSIE 4 DOM
   return document.all(objectId);
}
else if (document.layers && document.layers)
{
   // NN 4 DOM.. note: this won't find nested layers
   return document.layers;
}
else
{
   alert('取值失败未找到对应id');
}
}

function reloadvcode(obj)
{
$(obj).src="/index.php/vcode/"+Math.round(Math.random()*100000);
}

<img src="/index.php/vcode" style="vertical-align:middle;" width="57" height="20" id="vcodeimg"title="单击刷新" />

如何验证?

比如您引用验证码的表单页面 action="/index.php/contrl/func/"

那么 在 contrl.php这个控制器文件中的func 方法中
加入以下代码$this->load->helper('url');
$this->load->library('session');
if ($this->session->userdata['vcode'] != $_POST['vcode'] )
{
   show_error ('Bad news: 验证码输入不正确!');
}
else//校验成功
{
    //your code.....
}祝您好运

/////////////////////////////////
补充点 config.php 里面的
$config['sess_time_to_update']
根据自己的实际情况设置 否则session 无法更新

[ 本帖最后由 yz20sui 于 2008-9-23 01:49 编辑 ]

Hex 发表于 2008-9-23 00:04:00

我给楼主改了一下语法加亮!好文章,加分!

lxylxy888666 发表于 2008-9-23 10:20:18

感觉复杂,,我的比较简单些,
等我空了发出来..:)

moonster 发表于 2008-9-25 08:20:04

系统自带的也不错,哈哈

analyzer 发表于 2008-9-25 17:28:45

楼主不错,好文章,谢谢分享

chen_arou 发表于 2009-7-26 15:24:00

谢谢楼主

ffms_lin 发表于 2009-8-12 14:33:19

session值总是上一次图片中的数字?为什么啊!

chinawuyi 发表于 2009-11-9 03:37:31

我用了楼主的方法,也自己写了几个,都有这个问题,session的值永远是上次图片种的数字!

燃雲 发表于 2009-11-10 19:41:46

回复 8# chinawuyi

刚试过,没有问题,每次生成的图都不一样。

在想问题在哪。网上找来例子一试:


<?php

// Requires the GD Library
header("Content-type: image/png");
$im = imagecreatetruecolor(512, 512) or die("Cannot Initialize new GD image stream");
$white = imagecolorallocate($im, 255, 255, 255);
for ($y=0; $y<512; $y++)
{
      for ($x=0; $x<512; $x++)
      {
                if (rand(0,1) === 1)
                {
                        imagesetpixel($im, $x, $y, $white);
                }
      }
}
imagepng($im);
imagedestroy($im);
?>


在Linux上每次生成的图都不一样,在Windows上每次生成的图都一样!

问题应该是Windows上PHP的rand()函数并不随机所致。

不妨试试看!
页: [1]
查看完整版本: 验证码模型 For CodeIgniter