zoukankan      html  css  js  c++  java
  • 使用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)*1525string.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)


    效果大致如下:

  • 相关阅读:
    函数
    函数
    day---07 文件的操作
    作业9 DFA最小化,语法分析初步
    作业8 非确定的自动机NFA确定化为DFA
    作业7 正规式到正规文法与自动机
    作业6 正规文法与正规式
    作业5 词法分析程序的设计与实现
    作业四 文法和语言总结与梳理
    作业三 语法树,短语,直接短语,句柄
  • 原文地址:https://www.cnblogs.com/chutianyao/p/1783222.html
Copyright © 2011-2022 走看看