欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

ThinkPHP3.1快速入门(20)验证码

shiping1 的头像

获取扩展类库

ThinkPHP的扩展中由图像处理类Image以及用于生成随机验证码的字符处理类String共同完成验证码功能,可以在在http://www.thinkphp.cn/extend/225.html下载图像处理类以及http://www.thinkphp.cn/extend/266.html下载字符处理类,或者下载官方的完整扩展包(http://www.thinkphp.cn/down/253.html)里面也已经包含以上扩展类了。如果是单独下载的扩展类库,把解压后的Image.class.php和String.class.php 一起放入ThinkPHP/Extend/Library/ORG/Util/(如果没有请手动创建)目录下面。由于验证码显示采用了GD库支持,所以需要环境支持GD库。

生成验证码

生成验证码其实很简单,只需要在你的Action中添加操作方法,一般为了避免受权限控制的影响,我们通常把这个方法放到公共Action或者无需授权就能访问的控制器(例如PublicAction)中,下面我们以放到PublicAction控制器类中为例,代码如下:
  1. class PublicAction extends Action{
  2.     Public function verify(){
  3.         import('ORG.Util.Image');
  4.         Image::buildImageVerify();
  5.     }
  6.  }
复制代码
 
定义后,我们可以在任何需要验证码的模块中调用Public模块的verify方法来显示验证码,需要做的仅仅是在需要的模板中添加如下调用代码:
  1. <img src='!-APP-!/Public/verify/' />
复制代码
 
这样,我们访问该页面后就能看到默认的验证码图像显示,如下所示:

如果你的验证码不能正常显示,请检查:
  1. 是否已经安装GD库支持并正常开启;
  2. Image类库以及String类库是否在正确的位置以及是否正确导入;
  3. 验证码输出之前是否有任何的其他输出(尤其是UTF8的BOM头信息输出);
很多开发人员验证码无法显示的情况多数是由于文件中有输出或者BOM头的情况,关于UTF8的BOM头检测有工具可以检测,很多编辑器也支持去掉BOM保存(这个不清楚的话可以百度下)。这里要另外强调下很多开发人员在书写代码的时候不够规范,例如经常会有下面的情形发生:
在文件的开头有空行

在文件的尾部有空行

以上两种情况都会导致页面的其他输出,从而导致验证码出错。

验证码显示设置

默认情况下,验证码采用随机的4位数字显示,我们可以通过参数来设置不同的显示方式,Image类的buildImageVerify方法用法如下:
buildImageVerify 生成图像验证码
用法buildImageVerify($length,$mode,$type,$width,$height,$verifyName)
参数length验证码的长度,默认为4位数
model验证字符串的类型,默认为数字,其他支持类型有0 字母 1 数字 2 大写字母 3 小写字母 4中文 5混合
type验证码的图片类型,默认为png
width验证码的宽度,默认会自动根据验证码长度自动计算
height验证码的高度,默认为22
verifyName验证码的SESSION记录名称,默认为verify

验证输入

每次生成验证码的时候,就会通过SESSION记录本次的验证码的md5后的字符串信息,所以,要检查验证码是否正确,我们只需要在Action中使用下面的代码判断就行了:
  1. if(session('verify') != md5($_POST['verify'])) {
  2.    $this->error('验证码错误!');
  3.  }
复制代码
 
建议使用session方法来获取SESSION值,因为验证码生成方法里面也是采用的session方法保存的,可以避免受session前缀的影响而出错。这里的verify名称取决于你的验证码的verifyName参数的值。
如果你的session功能不正常,可能会导致验证码检测报错的情况发生。

中文验证码

BuildImageVerify方法不支持中文验证码的显示,如果需要显示中文验证码,请使用GBVerify方法,用法示例:
  1. Public function verify(){
  2.     import("ORG.Util.Image");
  3.     Image::GBVerify();
  4.  }
复制代码
 
显示效果如下:

如果能够显示图片,但是看不到图片中的中文字符,请检查是否有拷贝字体文件到图像类库所在目录。默认使用的字体文件是simhei.ttf(该文件可以从window的Fonts目录下面找到)。
GBVerify方法也有不同的参数用于设置验证码,具体用法如下:
GBVerify生成中文验证码
用法GBVerify ($length,$type,$width,$height,$fontface,$verifyName)
参数length:验证码的长度,默认为4位数
type:验证码的图片类型,默认为png
width:验证码的宽度,默认会自动根据验证码长度自动计算
height:验证码的高度,默认为50
fontface:使用的字体文件,使用完整文件名或者放到图像类所在的目录下面,默认使用的字体文件是simhei.ttf(该文件可以从window的Fonts目录下面找到
verifyName:验证码的SESSION记录名称,默认为verify

验证码刷新

如果随机生成的验证码看不清楚,就需要添加验证码刷新功能来重新生成,这个其实只是修改前端代码,后台的验证码生成方法无需修改。
一般我们是用js方法来控制验证码的刷新,例如下面可以实现点击验证码图片刷新验证码:
  1. <script language="JavaScript">
  2.  function fleshVerify(){ 
  3.     //重载验证码
  4.     var time = new Date().getTime();
  5.         document.getElementById('verifyImg').src= '!-APP-!/Public/verify/'+time;
  6.  }
  7.  </script>
  8.  <img id="verifyImg" src='!-APP-!/Public/verify/' onclick="fleshVerify()" />
复制代码
 
当然,熟悉Jquery的开发人员,可以用Jquery代码来简化验证码刷新的js方法,这个就不再多说了。
评论(57相关
Hi,Tony07月18日
回复 coolinglee : 图片路径不对吧,你要照抄得跟官方路径一样,!-APP-!/Public/verify/,另外介绍中的!-APP-!已经被摒弃了,记得换成__APP__
君临2014年11月23日
3.2
<img src='../Public/verify' />
君鸿2014年09月05日
三种显示不出来验证码情况都排除了,验证码的请求路径也按照其他评论进行修改了,但仍然显示不出验证码,到底是怎么回事啊!
回复君鸿2014年09月12日
今天看了教学视频又试了一次,还是不行,到底怎么回事啊???
回复且试天下201203月28日
回复 君鸿 : 你看的谁的教程
friendwrite2014年08月25日
<img src='!-APP-!/Public/verify/' />为什么这个路径没有用????是没定义路径封装么,求指教
回复绑定注册2014年08月26日
!-APP-! 的锅。。。。你自己改下啊!__APP__/ 你试试 。。。或者自定义url
回复friendwrite2014年08月28日
回复 绑定注册 : 恩恩,3Q
changup2014年08月22日
这个好;pass
smallfish2014年07月17日
<img src="__URL__/verify" onclick="changeimg()" id="verify" name="verify">
<script>function changeimg()
document.getElementById('verify').src="__URl__/verify"; 
</scirpt>
经测试这样才正确!
回复初学生03月12日
function fleshVerify(){
//重载验证码
var time = new Date().getTime();
document.getElementById('verifyImg').src='__URL__/verify'+time;
}
请问我这样写有问题吗?为什么点击刷新看不见验证了?
回复酷酷的07月30日
回复 初学生 : 在verify后面加个/试下 
document.getElementById('verifyImg').src='__URL__/verify/'+time;
sean_shanghai2014年05月07日
<img src='__APP__/Public/verify'/> 这个样子才可以显示的。。大家试试看吧!
回复lioo2014年05月20日
难怪我显示不出来,真棒!
回复paopaoshalj2015年01月26日
正确
回复初学生03月12日
能说说src表示的具体地址吗
ymenking2014年04月20日
按照教程写的,验证码出来一个X,图片显示不出来,查了GD库,是安装开启了的,二个文件也放进去了,不知为什么显示不出图片
回复coolinglee2014年11月25日
同有此类感觉啊,有没有告诉一声到底为什么啊
8921318952014年04月09日
為何我的验证码只是显示干扰线
回复梦海之巅12014年04月11日
引入Image.class.php时试试这样写:import('@.ORG.Util.Image');
回复8921318952014年05月08日
我的問題早已解決,不過還是非常感謝你的回覆!
654437342014年03月11日
IIS6下 开了debug也会显示不出验证码
回复tangyunfei2014年04月01日
谢谢了 非常感谢 我也遇到过IIS6下乱码 关了调试就正常了 坑爹呀
回复RobinZM2014年06月04日
回复 tangyunfei : II6 调试在哪关啊?我的验证码也不正常了,对IIS不熟啊,不知道调试在哪。
changcun2014年02月08日
刷新验证码的js为什么后面带个时间呢?
回复wanzhende2014年02月26日
同问,为何带个时间,是何故?难道跟CSS样式带时间是同样的功效?
回复wanzhende2014年02月26日
终于知道为什么了,因为浏览器在验证码图片的URL地址相同的时候,默认是采用缓存里的文件而不是最新的文件,加上time这个最后一个参数就是让验证码图片地址不同,这样浏览器就会用最新的图片来替换显示,用户就可以保证看到最新有效的验证码了
vilay2014年01月10日
检查是否正确的那段代码放哪啊,手册看不到
回复wanzhende2014年02月26日
放到登录验证控制器里对应的操作方法里面,可以根据需要来选择是否用AJAX
sdnt2013年11月29日
有配置文件怎么不显示
hanqing2013年11月28日
三种方式都排除了 为什么还是不显示验证码?
回复ymenking2014年04月20日
我也是这样,找不出原因
tree1002013年11月23日
挺好用的说。。
jiewuzhe022013年11月16日
xuexila
fengxiaoning2013年11月11日
为什么我的中文验证码显示不出来?只有干扰线,没有中文呀
回复梦海之巅12014年04月11日
引入Image.class.php时试试这样写:import('@.ORG.Util.Image');可以不
wonderj2013年09月24日
报错提示ORG\Util\Image.class.php没有定义imagecreate()
拐弯后2013年09月02日
混合型的怎么区分不了大小写???
zuanke2013年08月29日
学习了,http://www.zhashutiao.com。只不过这背景色还有杂色怎么设置
xleeding2013年08月28日
中文验证码搞了好久,能显示图片但不显示文字,求大虾们帮助
回复Hi,Tony07月18日
如果能够显示图片,但是看不到图片中的中文字符,请检查是否有拷贝字体文件到图像类库所在目录。默认使用的字体文件是simhei.ttf(该文件可以从window的Fonts目录下面找到)
cyfltt2013年08月20日
没Gd2就显示不了吗? 我在本地是gd2显示 的 传到服务器是gd就显示不了 了
lxlin3152013年08月19日
不错,弄出来了,不过我是写成
  1. __APP__/Public/verify/
复制代码
 
复制代码
 
复制代码
 
复制代码
 
这样才弄出来的,还没有部署到服务器,不知道部署后会不会出错
回复duty32014年02月19日
是啊。
这篇的作者跟之前的作者不是同一个人吗?怎么配置不同意啊
回复wanzhende2014年02月26日
猜想他们是故意的,因为这个网站也用ThinkPHP开发,他们估计是担心__APP__这个字符被模版引擎替换,所以用<!-APP-!>来表示?不是版本升级了原来的表示符进行了更换?
回复欧小默默2014年06月01日
正解。__APP__/Public/Verify/
回复初学生03月12日
可是,我的verify方法是在LoginAction.class.php下啊,改成__APP__/Login/verify,为什么不行啊?
未来倒影2013年08月18日
这个不错
phantomshop2013年08月16日
Image::buildImageVerify(4,2,'png',60,30,'qwe');
参数怎么没效呀
shengyanwei2013年08月07日
有些无语了,验证码正常显示,就是提交上去验证的时候一直不正确,打印session也没有记录,求大神帮忙
phpsoft2013年08月07日
这个可以有
勿忘我网2013年08月01日
定义后,我们可以在任何需要验证码的模块中调用Public模块的verify方法来显示验证码,需要做的仅仅是在需要的模板中添加如下调用代码: 这个模版文件是哪个文件,加在哪个位置
回复旧得很好看2013年08月04日
哪里需要验证码,这段代码就放到哪里,比如登陆模板文件
回复随缘的天空2013年08月13日
回复 旧得很好看 :
勿忘我网2013年08月01日
生成验证码其实很简单,只需要在你的Action中添加操作方法,一般为了避免受权限控制的影响,我们通常把这个方法放到公共Action或者无需授权就能访问的控制器(例如PublicAction)中,下面我们以放到PublicAction控制器类中为例,代码如下: 这个文件在哪
回复hailangswpu2013年08月07日
这个文件就在你项目文件的lib目录下的Action目录里面。比如我的是mythink/app/lib/Acton/PublicAction.class.php
itbaby2013年07月31日
原来是这样啊。
myfirtyou2013年07月30日
实然觉得我的积分好少 加油回复
w00852013年06月03日
000
goodgood2013年05月21日
我的thinkphp页面中使用验证码 显示全部为乱码 字符集我都统一为utf-8 这个怎么解决啊?
dqk19852013年04月08日
验证码刷新 你这里的代码应该不对
吧,你这里的用js替换成了__APP__这样thinkphp模版就不会再次解悉了。所以地址就成了__APP__/....这样肯定不对啊?
回复lcy20002013年05月18日
__PUBLIC__
xingkong12212013年03月21日
这个验证居然会区分大小写
回复lcy20002013年05月18日
MD5当然区分大小写
bys_11232013年03月21日
报错:Class 'String' not found D:\Site\xiangmu\include\tpdsk\Lib\ORG\Util\Image.class.php 第 333 行. 我已经把String类正确导入了啊,和Image的类在一起啊
回复bys_11232013年03月21日
使用的是GBVerify(),把buildImageVerify中import的@去掉,问题同样
回复bys_11232013年03月21日
好吧,研究了下import,把GBVerify()的代码import加上@就好了,不知道为什么这两个方法要一个有@一个没有
回复bys_11232013年03月21日
好吧,研究了下import,把GBVerify()的代码import加上@就好了,不知道为什么这两个方法要一个有@一个没有
回复m1992013年04月07日
在image.class.php第332行修改:
import('@.ORG.Util.String');
heikeyuit2013年03月20日
我用的是2.1的版本,验证码正常显示,可是我现在用3.1的版本,由于核心版本缺少ORG目录,我添加扩展中的ORG及其目录文件。但是现在为什么 提示缺少 Image 类,愁死我了,有知道的麻烦告诉我呗
回复lcy20002013年05月18日
用完整版呗
萝卜茄子2013年03月19日
在 'URL_MODEL' => '2',的模式下,以上方法无效,验证码不能正常输出。不知怎么解决???
回复m1992013年04月07日
验证码显示不出来,可以直接输入验证码显示地址:如localhot/app/index.php/Public/verify来调试,即可报出错误来。
霜之哀伤2013年03月14日
验证码字母也太小了吧,调整下高度和宽度也只是方框面积大了,里边的字母还是那么小,坑爹啊
回复xqlu2013年05月11日
是啊,我看了看代码,他们在代码里控制的字号,不能在外边控制。
haran2013年03月07日
本机测试正常。上传到服务器就不行。提示找不到Image类。服务器其他系统验证码正常。
ntuchenxy2013年02月23日
session改成db类型后,验证码出不来了
2012梦幻之灵2013年01月16日
我的中文验证码怎么不行啊!!!!!显示不出来中文 !!!字体文件我都拷贝到了图像类库目录下了啊!!!!
回复charisma2013年04月01日
public function verify(){
import('ORG.Util.Image');
//Image::buildImageVerify(); 
Image::GBVerify();
if(session('verify')!=md5($_POST['verify']))
{
$this->error("验证码错误");
}
回复竹风2013年05月07日
我的也是,你的好了吗?是怎么回事啊?
AlienJun2013年01月08日
乱码??
thinkphphj2013年01月08日
验证码的搞大点,不然眼睛得累
回复charisma2013年04月02日
你可以设置长宽高啊
回复xqlu2013年05月11日
回复charisma:一看你就没有试过。
byonds2013年01月07日
我加了多语言,验证码就不显示了'CheckLang'这个去掉验证码又可以显示了,请问这是怎么回事
飘荡之神2013年01月06日
好玩的很
凡人和悲剧英雄2013年01月04日
啊哈,用的sublime啊
K2012年12月26日
请问怎么配合JQ呢?
虽然我大量页面都有JQ,但能不用的都没用..个别的.包括登陆首页就没用JQ
K2012年12月24日
src= '__APP__/Public/verify/'+time; 关于URL这里请问有没有一个可可移植性的写法?一旦url_model换成0就那啥了。。
我目前的做法是src= '{:U("Public/verify?xx=xxx")}'.replace('xx', time);
回复thinkphp2012年12月25日
这个当然可以 利用U函数配合Jquery即可 文档里面只是举个例子而已。
回复phantomshop2013年08月16日
Call to undefined function imagecreate()
这个错误是为什么呢
kamon2012年12月23日
是否可以调节杂点?有客户提出杂点太多看不清,我晕。我目前只有把344~346行杂点的代码注掉了。
/hl龙龙2012年12月21日
我测的中文验证码为什么是乱码,字体放到目录下面了,页面编码utf-8,输出英文正常,中文是乱码,求大神帮忙
回复笑熬浆糊2013年02月21日
你是用什么方法的??
xiao01272012年12月20日
官网的验证码是怎么弄的啊,感觉更好看
回复thinkphp2012年12月22日
官方是下一代的验证码,哈哈~
TMDYYZC2012年12月20日
只有中文验证码可用了。英文验证码轻而易举被破解了!55
gcq9112012年12月19日
生成验证码的程序建议修改一下,改成可以设置字体跟字号的,现在无法使用字体,而且字号偏小,如果用大的验证码图片,就显得不好看了。
回复thinkphp2012年12月25日
下一代的验证码类库会很快出来的,官网的验证码就是一个例子。
l68970322012年12月18日
TP里面的验证码样式有没得改变的。。总觉得这验证码不好看
thinkphp2012年12月18日
加上随机数是为了避免某些环境下图片被缓存~
回复shjyy2012年12月18日
宽度与高度是聋子耳朵配盘的...改了宽度与高度,验证码字体的大小又不改变木有用...
gongzhq2012年12月18日
验证码刷新加上随机数起什么作用呢,我在firefox中不加随机数直接document.getElementById('verifyImg').src= '__APP__/Public/verify/';就可以刷新啊
回复lyongde2012年12月18日
避免缓存

普通分类: