使用Lua GD库动态生成验证码图片(2)

在前一篇文章中初步的实现了验证码的随机生成,觉得很容易被破解,因此加了一些干扰;

鹤冲天建议使用表达式作为验证码,即使破解程序识别了验证码,也要计算结果才能通过验证,在一定程度上增加了破解难度。


因此我对代码进行了重新整理,通过控制运行时配置选项来达到不同效果。

现在主要做到了:

(1)字符内容随机(普通字符串或表达式)

(2)每个字符的字体随机

(3)每个字符大小随机

(4)每个字符倾斜角度随机

(5)干扰线条随机

除了(4)其他都可以通过配置来控制。


下面是代码,有详细的注释,就不多说了:

  1  require ( " gd " )
  2  require ( " lfs " )
  3 
  4  -- ---------------------------------------------------------------------------------------------------------------------------------
  5  -- 运行配置项
  6  -- ---------------------------------------------------------------------------------------------------------------------------------
  7  -- 字体:-1-使用gd.FONT_GIANT字体;1-使用随机字体;其他-使用“fonts”中第一个字体
  8  -- 字体预先在变量“fonts”中定义;如果fonts没有值,将搜索系统中的所有字体,字体路径在“FONT_PATH”中预定义
  9  FONT = 1
 10 
 11  -- 每个字符字体随机:1-是,其他-否
 12  -- 仅当“FONT”值为“1”时,本变量起作用
 13  FONT_RANDOM_CHAR = 0
 14 
 15  -- 每个字符字体大小是否随机:1-是,其他-否
 16  -- 仅当FONT^=-1时起作用
 17  FONT_SIZE_RANDOM = 1
 18 
 19  -- 是否增加线条干扰:1-是;其他-否
 20  XLINE_FALG = 1
 21 
 22  -- 干扰线条的最多条数
 23  -- 仅当“XLINE_FALG”的值为“是”是,本变量起作用
 24  XLINE_LIMIT = 6
 25 
 26  -- 验证码类型:TEXT-字符串;EXPRESSION-表达式
 27  MARK_TYPE = " TEXT "
 28  -- MARK_TYPE="EXPRESSION"
 29 
 30  -- 字符个数:仅当“MARK_TYPE”=“TEXT”时,本变量起作用
 31  TEXT_NUM = 6
 32 
 33  -- 表达式项数限制(最多不超过EXPRESSION_ITEMS项):仅当“MARK_TYPE”=“EXPRESSION”时,本变量起作用
 34  EXPRESSION_ITEMS = 3
 35 
 36  -- 生成验证码个数
 37  MARK_NUM = 100000
 38 
 39 
 40  -- ---------------------------------------------------------------------------------------------------------------------------------
 41  -- 预定义变量
 42  -- ---------------------------------------------------------------------------------------------------------------------------------
 43  -- 词典
 44  dict = { ' 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 ' , ' 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 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' 0 ' }
 45  numbers = { " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 " , " 9 " } -- 表达式可使用数字,排除0
 46  operators = { " + " , " - " , " * " } -- 表达式可使用运算符,不支持“/”
 47 
 48  -- 随机种子,防止通过获取系统时间得到随机数种子,直接计算出验证码
 49  math.randomseed ( os.time ())
 50 
 51  -- 大小
 52  IMG_WIDTH = 100
 53  IMG_HEIGHT = 40
 54 
 55  -- 颜色
 56  im2  =  gd.createTrueColor(IMG_WIDTH,IMG_HEIGHT)
 57  fg  =  im2:colorAllocate( 129 , 32 , 28 ) -- 前景色
 58  bg  =  im2:colorAllocate( 216 , 235 , 238 ) -- 背景色
 59 
 60  -- 字体
 61  FONT_PATH = " C:/WINDOWS/Fonts/ " -- 系统字体路径
 62  fonts = {}
 63  -- fonts={"courbd.ttf","courbi.ttf","DejaVuMonoSans.ttf","DejaVuMonoSansBold.ttf","DejaVuMonoSansBoldOblique.ttf","DejaVuMonoSansOblique.ttf","lucon.ttf","monosbi.ttf","nina.ttf","simhei.ttf","simkai.ttf","swissci.ttf","tahomabd.ttf","timesbd.ttf","timesbi.ttf","timesi.ttf","trebuc.ttf","trebucit.ttf"}
 64  font_size = { 14 , 15 , 16 , 17 , 18 , 19 , 20 } -- 随机字体大小
 65 
 66  -- 生成的随机码
 67  stringmark = ""
 68 
 69  -- ---------------------------------------------------------------------------------------------------------------------------------
 70  -- 功能函数
 71  -- ---------------------------------------------------------------------------------------------------------------------------------
 72  -- 初始化:创建图片、设置背景
 73  function  init()
 74      im2  =  gd.createTrueColor(IMG_WIDTH, IMG_HEIGHT)
 75      im2:filledRectangle( 0 , 0 ,IMG_WIDTH,IMG_HEIGHT,bg)
 76      stringmark = ""
 77  end
 78 
 79  -- 查找字体
 80  function  searchFont()
 81       if  table.getn(fonts) == 0   then   -- 没有指定字体,就搜索系统字体
 82           local  i = 1
 83           for  file  in  lfs.dir(FONT_PATH)  do
 84               if   string.find (file, " .ttf " ) and   not   string.find (file, " esri " )   then   -- 排除特定字体
 85                  fonts[i] = file
 86                  i = i + 1
 87               end
 88           end
 89       end
 90  end
 91 
 92  -- 生成text字符串
 93  function  makeText()
 94       local  num = table.getn(dict)
 95       for  i = 1 ,TEXT_NUM  do
 96          stringmark = stringmark..dict[ math.random (num)]
 97       end
 98  end
 99 
100  -- 生成表达式字符串
101  function  makeExpression()
102       local  n = math.random ( 2 , 3 ) -- 表达式项数
103       local  strings = {}
104       for  i = 1 ,n * 2 - 1   do -- 表达式项数+运算符项数
105           local  str = ""
106           if  i % 2 == 1   then -- 数字
107               local  n2 = math.random ( 1 , 2 )
108               for  j = 1 ,n2  do -- 每个数字最多2位
109                  str = str..numbers[ math.random ( 9 )]
110               end
111           else -- 运算符
112              str = operators[ math.random ( 3 )]
113           end
114          strings[i] = str
115       end  
116       return  strings
117  end
118 
119  -- 主函数
120  function  doIt()
121      searchFont()
122       local  numfonts = table.getn(fonts)
123       if  numfonts < 1   then
124           print ( " 没有找到字体! " )
125           return
126       end
127 
128       for  i = 1 ,MARK_NUM  do
129          init()
130           local  font = fonts[ 0 ];
131           local  fontsize = 20 ;
132          
133           if  MARK_TYPE == " TEXT "   then -- 普通字符串验证码
134              makeText()
135  --             print(stringmark)    
136               if  FONT ==- 1   then
137                  im2:string(gd.FONT_GIANT, 18 , 10 ,stringmark, fg)
138               else
139                   for  nIndex = 1 , string.len (stringmark)  do
140                       if  FONT == 1   then  font = fonts[ math.random (numfonts)]  end
141                       if  FONT_SIZE_RANDOM == 1   then  fontsize = font_size[ math.random ( 7 )]  end
142                      im2:stringFT(fg,FONT_PATH..font,fontsize, math.random () / math.pi , 5 + (nIndex - 1 ) * 15 25 string.sub (stringmark,nIndex,nIndex))
143                   end         
144               end
145           elseif  MARK_TYPE == " EXPRESSION "   then -- 表达式验证码
146               local  strings = makeExpression()
147               local  raise = 0
148               local  ncharacter = 0  
149               for  j = 1 ,table.getn(strings)  do
150                   if  j % 2 == 0   then  raise = 3   end
151                  stringmark = stringmark..strings[j]
152                   if  FONT == 1   then  font = fonts[ math.random (numfonts)]  end
153                   if  FONT_SIZE_RANDOM == 1   then  fontsize = font_size[ math.random ( 5 )]  end           
154                  im2:stringFT(fg,FONT_PATH..font,fontsize, math.random () / math.pi , 5 + ncharacter * 12 + raise,  25 , strings[j])
155                  ncharacter = ncharacter + string.len (strings[j])
156               end
157  --             print(stringmark) 
158  --             value=tonumber(stringmark)
159  --             print(value)
160           end
161          
162           --   随机线条干扰
163           if  XLINE_FALG == 1   then
164               local  xlineNum = math.random (XLINE_LIMIT)
165               for  i = 1 ,xlineNum  do
166                  im2:line( math.random (IMG_WIDTH), math.random (IMG_HEIGHT), math.random (IMG_WIDTH), math.random (IMG_HEIGHT),fg)
167               end
168           end
169 
170          im2:png( " ./output/ " ..font.. " .png " , 100 )                
171       end
172  end
173 
174 -- start = os.clock ()
175  doIt()
176 -- print ( os.clock () - start)


效果大致如下:

转载于:https://www.cnblogs.com/chutianyao/archive/2010/07/22/1783222.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值