主题:  CFMX生成验证码

Mozier

职务:管理员
等级:5
金币:11.0
发贴:2994
注册:2004/1/12 17:26:30
#12004/10/24 23:31:53
image.cfm
<!-- ////////////////////////////////////////////////
  Source Code Copyright by Mozier, blog.coolog.com
  Application: validateCode 
  Supported CF Version: CFMX
  File Name: image.cfm
  Created By: Mozier (Mozier at 163.com)
  Created Date: 2004/10/24
  Description: create validate code
  Version History: yyyy/mm/dd   Version    Comments
                   2004/10/24     1.0       created
  ///////////////////////////////////////////////////
 -->
<!---******************加载系统字体************************* --->
<cffunction name="loadSystemFont"  access="private" output="false" returntype="any">
  <cfargument name="fontName" required="no" type="string" default="Georgia" />
  <cfargument name="size" required="no" type="numeric" default="18" />
  <cfargument name="style" required="no" type="string" default="italic" />
  <cfset var font = createObject("Java","java.awt.Font") />
  <cfreturn font.decode("#arguments.fontName#-#ucase(arguments.style)#-#arguments.size#") />
</cffunction>
<!-- ******************产生随机数字和字母******************** -->
<cffunction name="getRandomCode" access="private" returntype="string" output="false">
  <cfargument name="length" type="numeric" required="no" default="4"/>
  <cfset var charList = "A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9" />
  <cfset var randomCode=""/>
  <cfloop from="1" to="#arguments.Length#" index="i">
    <cfset thisNum = RandRange(1,listlen(charList, "|")) />
    <cfset thisChar = ListGetAt(charList, thisNum, "|") />
    <cfset randomCode = ListAppend(randomCode, thisChar, " ") />
  </cfloop>
  <cfset randomCode = replace(randomCode, " ", "", "all") />
  <cfreturn randomCode />
</cffunction>
<!-- ***********************创建图形******************************* -->
<cffunction name="createImage" access="private" returntype="any" output="false">
  <cfargument name="width" type="numeric" required="no" default="70" />
  <cfargument name="height" type="numeric" required="no" default="25" />
  <!-- 创建JAVA类 -->
  <cfset var image = createObject("java","java.awt.image.BufferedImage") />
  <cfset var color=createObject("java","java.awt.Color") />
  <!-- 定义字体样式 -->
  <cfset fontStyle=loadSystemFont() />
  <!-- 在内存中创建图象 -->
  <cfset image.init(javaCast("int",arguments.width),javaCast("int",arguments.height),image.TYPE_INT_RGB) />
  <!-- 获取图形 -->
  <cfset g = image.getGraphics() />
  <!-- 设定背景色 -->
  <cfset g.setColor(color.white) />
  <cfset g.fillRect(0,0,javaCast("int",arguments.width),javaCast("int",arguments.height)) />
  <!-- 获取随机产生的认证码 -->
  <cfset code=getRandomCode() />
  <!-- 将认证码写入SESSION用于比较 -->
  <cfset session.code=code />
  <!-- 将认证码显示到图象中 -->
  <cfset g.setColor(color.black) />
  <cfset g.setFont(fontStyle) />
  <cfset g.drawString(code,javaCast("int",12),javaCast("int",18)) />
  <!-- 使图象生效 -->
  <cfset g.dispose() />
  <cfreturn image />
</cffunction>
<!-- ***************************************************************** -->
<cfscript>
//定义图像存放路径
path=getDirectoryFromPath(expandPath("*.*"));
outputStream = createObject("java","java.io.FileOutputStream");
imageIO = createObject("java","javax.imageio.ImageIO");
outputStream.init("#path#code.png");
// 输出图象到本地
imageIO.write(createImage(),"png",outputStream);
</cfscript>
<!-- 输出图象到页面 -->
<cfcontent type="image/x-png" file="#path#code.png" />
<!-- 设置页面不被缓存 -->
<cfheader name="Pragma" value="no-cache" />
<cfheader name="Cache-Control" value="no-cache" />
<cfheader name="Expires" value="0" />


应用:
<img src="image.cfm" />


验证的时候将输入值和session.code比较,不相同则返回一个错误,比如:
<cfif CompareNoCase(session.code,FORM.validate) eq 0>
<cfset error="验证码正确" />
<cfelse>
<cfset error="验证码错误">
</cfif>
<cfoutput>#error#</cfoutput>


当然在此基础上还可以给验证码加随机背景色或随机雪花点之类的,就看你怎么去做了,只要肉眼能看清~

演示:
www.coolog.com/temp/authcode/test.cfm



网络白痴 | 5D荣誉斑竹

职务:普通成员
等级:4
金币:10.0
发贴:1657
注册:2001/1/5 16:32:35
#22004/10/25 9:09:29
cool



吃鱼专家

职务:普通成员
等级:6
金币:11.0
发贴:5312
注册:2004/1/17 13:07:16
#32004/10/26 8:51:15
<cfset var charList = "A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z" />

把charlist改成这样就可以出现小写字母了

<cfif Compare(session.code,FORM.validate) eq 0>
<cfset error="验证码正确" />
<cfelse>
<cfset error="验证码错误">
</cfif>
<cfoutput>#error#</cfoutput>



Mozier

职务:管理员
等级:5
金币:11.0
发贴:2994
注册:2004/1/12 17:26:30
#42004/10/26 9:03:35
嗯,写的时候本来有小写的,后来就模仿QQ.com的验证码,全改成大写了~



吃鱼专家

职务:普通成员
等级:6
金币:11.0
发贴:5312
注册:2004/1/17 13:07:16
#52004/10/26 9:37:45
不过我觉得你生成随机数太繁了,可以取CREATEUUID()中的4位就行了
要小写的话就在外边加个tobase64()



Mozier

职务:管理员
等级:5
金币:11.0
发贴:2994
注册:2004/1/12 17:26:30
#62004/10/26 10:06:21
截去uuid的前4位是个好想法,省事~

getRandomCode()是我以前写的,函数可以返回数字,字母(大小写),数字字母混合,这里我把它精简了,只返回数字和字母的混合~



小龟蛋

职务:普通成员
等级:1
金币:0.0
发贴:34
注册:2003/3/11 18:50:24
#72004/11/5 14:58:12
连续地createUUID, 产生的字符串会比较相似. 可以写得简单点:

char="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
randCode="";
for(i=1;i lt length;i=i+1){
randCode="#mid(char,RandRange(1,len(char)),1)##randCode#";
}

如果要生成的文字抗锯齿, 可以这样:
at=createObject("java","java.awt.geom.AffineTransform").init();
fontRC=createObject("java","java.awt.font.FontRenderContext").init(at,true,false);
textLO=createObject("java","java.awt.font.TextLayout").init(randCode,font,fontRC);
g.setPaint(color.init(colorCode,true));
textLO.draw(g,x,y);