使用Lua GD库动态生成验证码图片(2)
2010-07-22 18:02
696 查看
在前一篇文章中初步的实现了验证码的随机生成,觉得很容易被破解,因此加了一些干扰;
鹤冲天建议使用表达式作为验证码,即使破解程序识别了验证码,也要计算结果才能通过验证,在一定程度上增加了破解难度。
因此我对代码进行了重新整理,通过控制运行时配置选项来达到不同效果。
现在主要做到了:
(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
--生成表达式字符串
function makeExpression()
local n=math.random(2,3)--表达式项数
local strings={}
for i=1,n*2-1 do--表达式项数+运算符项数
local str=""
if i%2==1 then--数字
local n2=math.random(1,2)
for j=1,n2 do--每个数字最多2位
str=str..numbers[math.random(9)]
end
else--运算符
str=operators[math.random(3)]
end
strings[i]=str
end
return strings
end
--主函数
function doIt()
searchFont()
local numfonts=table.getn(fonts)
if numfonts<1 then
print("没有找到字体!")
return
end
for i=1,MARK_NUM do
init()
local font=fonts[0];
local fontsize=20;
if MARK_TYPE=="TEXT" then--普通字符串验证码
makeText()
-- print(stringmark)
if FONT==-1 then
im2:string(gd.FONT_GIANT,18,10,stringmark, fg)
else
for nIndex=1,string.len(stringmark) do
if FONT==1 then font=fonts[math.random(numfonts)] end
if FONT_SIZE_RANDOM==1 then fontsize=font_size[math.random(7)] end
im2:stringFT(fg,FONT_PATH..font,fontsize,math.random()/math.pi,5+(nIndex-1)*15, 25, string.sub(stringmark,nIndex,nIndex))
end
end
elseif MARK_TYPE=="EXPRESSION" then--表达式验证码
local strings=makeExpression()
local raise=0
local ncharacter=0
for j=1,table.getn(strings) do
if j%2==0 then raise=3 end
stringmark=stringmark..strings[j]
if FONT==1 then font=fonts[math.random(numfonts)] end
if FONT_SIZE_RANDOM==1 then fontsize=font_size[math.random(5)] end
im2:stringFT(fg,FONT_PATH..font,fontsize,math.random()/math.pi,5+ncharacter*12+raise, 25, strings[j])
ncharacter=ncharacter+string.len(strings[j])
end
-- print(stringmark)
-- value=tonumber(stringmark)
-- print(value)
end
-- 随机线条干扰
if XLINE_FALG==1 then
local xlineNum=math.random(XLINE_LIMIT)
for i=1,xlineNum do
im2:line(math.random(IMG_WIDTH),math.random(IMG_HEIGHT),math.random(IMG_WIDTH),math.random(IMG_HEIGHT),fg)
end
end
im2:png("./output/"..font..".png",100)
end
end
--start=os.clock()
doIt()
--print(os.clock()-start)
效果大致如下:
鹤冲天建议使用表达式作为验证码,即使破解程序识别了验证码,也要计算结果才能通过验证,在一定程度上增加了破解难度。
因此我对代码进行了重新整理,通过控制运行时配置选项来达到不同效果。
现在主要做到了:
(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
--生成表达式字符串
function makeExpression()
local n=math.random(2,3)--表达式项数
local strings={}
for i=1,n*2-1 do--表达式项数+运算符项数
local str=""
if i%2==1 then--数字
local n2=math.random(1,2)
for j=1,n2 do--每个数字最多2位
str=str..numbers[math.random(9)]
end
else--运算符
str=operators[math.random(3)]
end
strings[i]=str
end
return strings
end
--主函数
function doIt()
searchFont()
local numfonts=table.getn(fonts)
if numfonts<1 then
print("没有找到字体!")
return
end
for i=1,MARK_NUM do
init()
local font=fonts[0];
local fontsize=20;
if MARK_TYPE=="TEXT" then--普通字符串验证码
makeText()
-- print(stringmark)
if FONT==-1 then
im2:string(gd.FONT_GIANT,18,10,stringmark, fg)
else
for nIndex=1,string.len(stringmark) do
if FONT==1 then font=fonts[math.random(numfonts)] end
if FONT_SIZE_RANDOM==1 then fontsize=font_size[math.random(7)] end
im2:stringFT(fg,FONT_PATH..font,fontsize,math.random()/math.pi,5+(nIndex-1)*15, 25, string.sub(stringmark,nIndex,nIndex))
end
end
elseif MARK_TYPE=="EXPRESSION" then--表达式验证码
local strings=makeExpression()
local raise=0
local ncharacter=0
for j=1,table.getn(strings) do
if j%2==0 then raise=3 end
stringmark=stringmark..strings[j]
if FONT==1 then font=fonts[math.random(numfonts)] end
if FONT_SIZE_RANDOM==1 then fontsize=font_size[math.random(5)] end
im2:stringFT(fg,FONT_PATH..font,fontsize,math.random()/math.pi,5+ncharacter*12+raise, 25, strings[j])
ncharacter=ncharacter+string.len(strings[j])
end
-- print(stringmark)
-- value=tonumber(stringmark)
-- print(value)
end
-- 随机线条干扰
if XLINE_FALG==1 then
local xlineNum=math.random(XLINE_LIMIT)
for i=1,xlineNum do
im2:line(math.random(IMG_WIDTH),math.random(IMG_HEIGHT),math.random(IMG_WIDTH),math.random(IMG_HEIGHT),fg)
end
end
im2:png("./output/"..font..".png",100)
end
end
--start=os.clock()
doIt()
--print(os.clock()-start)
效果大致如下:
相关文章推荐
- 使用Lua GD库动态生成验证码图片
- PHP使用GIFEncoder类生成的GIF动态图片验证码
- PHP使用GIFEncoder类生成的GIF动态图片验证码
- 使用silverlight构建一个工作流设计器(十四)(动态生成流程图片下载_下)
- 使用 PIL 生成验证码图片
- 使用Python生成验证码图片
- 使用Servlet动态生成图片
- 【java】注册功能动态验证码的生成和验证(完整图片验证码封装工具类)
- Silverlight中生成并使用验证码图片
- 使用silverlight构建一个工作流设计器(十三)(动态生成流程图片下载_上)
- PHP使用GD库生成图像验证码
- 使用Response输出随机图片(随机生成验证码)
- ASP.NET动态生成图片样式的验证码
- 使用Java Servlet动态生成图片
- java随机动态生成汉字验证码图片的实例代码分享
- 使用JavaCV对视频截取图片,生成视频JPG封面图和GIF动态图
- 使用 Python 生成类数字字母混合验证码图片
- 使用ashx文件生成验证码图片
- Pyhton每日练习 08 使用 Python 生成类似于下图中的字母+数字验证码图片
- php使用GD库生成验证码