侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

反SPAM新思路―换Z-BLOG的验证码!

技术  /  管理员 发布于 7年前   206

最近我们一些Z-BLOGGER都在想做个什么插件拦住SPAM,当然解决方法也不是没有,就是弄个超强的服务器,可惜搞不起。那……我们只好从SPAMMER的角度来想了。
  懂一些的人可能知道,SPAM软件的基本原理是[搜索目标]-进入网站-扫描验证码-OCR-[填写表单]-POST。每一步我们都可以加以防范,比较现实的是防止SPAM软件成功的OCR出验证码。Z-BLOG自带的验证码实在有点弱,干扰点等于没有,感觉可以轻易的分析出验证码里的数字。解决方法就是――换一个验证码程序。 
  这个验证码程序(就是我现在用的)是从月光留言本里挖出来的,稍加修改,以便适应Z-BLOG。个人认为要编出软件OCR这个验证码是有点难度的,应该可以换取片刻的安宁。当然,这只是权宜之计,如果广泛使用,势必还会有高手来破解的。所以啊……最好官方能弄个服务器,有时候,我觉得商业化或是适当引进投资也是不错的~
目前还在测试效果,3-28晚开始。到目前(07-03-30)为止共收到1个SPAM(包括被拦截的。),内容和别的SPAM不一样,应该不是那个垃圾SEO网站的作品(很大胆的加了2个链接),而且不是提交在在一般搜索引擎搜索进来的《google加了一个网页恶意软件检测?》,而是在我的留言本。根据REFERER的结果应该是从主页过去的(也不排除从别的地方进去而没有执行脚本或提交refer信息),怀疑为人工SPAM(UPDATE:Haphic也收到了一个同样的。到底是不是人工的?他用的验证码是原版的……),换验证码的效果还需继续观察……

c_validcode.asp代码

复制代码 代码如下:

<%@ CODEPAGE=65001 %>
<% Option Explicit %>
<% 
'On Error Resume Next
 %>
<!-- #include file="../c_option.asp" -->
<!-- #include file="../function/c_function.asp" -->
<%

Response.buffer=true

Call Com_CreatValidCode("CheckCode")

Rem 生成验证码图片
Sub Com_CreatValidCode(pSN)
    Const codeLenMin = 5                '验证码位数范围
    Const codeLenMax = 5                '验证码位数范围
    Const cOdds = 2                         '杂点出现的机率
    Const dbtTimes = 1                    '干扰次数
    Const posX = 3                            '位置随机范围X
    Const posY = 2                            '位置随机范围Y
    ImgWidth = 60                            '图像宽(要为4的倍数)
    ImgHeight = 20                            '图像高

    Const cAmount = 10                     '字库数量
    Const cCode = "0123456789"    '字库对应的字符
    Const UnitWidth = 16                '字宽(要为4的倍数)
    Const UnitHeight = 15                '字高
    Const DotsLimit = 10                '每次删除有效点的上限(避免无法人为识别)
    Const tryCount = 5                    '避免删除有效点超过上限的尝试次数限制

    '-----------

    Randomize
    Dim i,ii,iii,flag,ActUnitWidth,ImgYuWidth,codeLen,ImgWidth,ImgHeight
    codeLen = codeLenMin + cint(Rnd*(codeLenMax-codeLenMin))
    If ImgWidth Mod 4 <> 0 Or ImgWidth < codeLen*UnitWidth Then ImgWidth = codeLen*UnitWidth
    If ImgHeight < UnitHeight Then ImgHeight = UnitHeight

    ' 禁止缓存
    Response.Expires = -9999
    Response.AddHeader "Pragma","no-cache"
    Response.AddHeader "cache-ctrol","no-cache"
    Response.ContentType = "Image/BMP"

    ' 颜色的数据(字符,背景)
    Dim vColorData(1)
    vColorData(0) = ChrB(0) & ChrB(0) & ChrB(0)  ' 蓝0,绿0,红0(黑色)前景色
    vColorData(1) = ChrB(255) & ChrB(255) & ChrB(255) ' 蓝250,绿236,红211(浅蓝色)背景色

    ' 字符的数据(可以自己修改,如果修改了尺寸,记得把前面的设定也改了)
    Dim vNumberData(9)
    vNumberData(0) = "111111111111111111110000000011111110000000000111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111001111110011111100111111000000000011111110000000011111111111111111111"
    vNumberData(1) = "111111111111111111111100011111111111000001111111111000000111111111001100011111111111110001111111111111000111111111111100011111111111110001111111111111000111111111111100011111111111110001111111111000000000111111100000000011111111111111111111"
    vNumberData(2) = "111111111111111111111100000111111111100000001111111100011100111111100011110011111111111110011111111111110011111111111110011111111111110011111111111110011111111111110011110011111110011111001111111000000000111111100000000011111111111111111111"
    vNumberData(3) = "111111111111111111111000000111111111000000001111111001111110011111100111110011111111111110011111111111100011111111111110001111111111111110011111111111111100111111100111111001111110011111100111111100000000111111111000000111111111111111111111"
    vNumberData(4) = "111111111111111111111111001111111111101100111111111100110011111111110011001111111110011100111111110011110011111110000000000000111000000000000011111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
    vNumberData(5) = "111111111111111111100000000001111100000000000111110011111111111111001111111111111100111111111111110011000000111111000001111001111111111111100111111111111110011111111111111001111100111111100111110011111110011111100000000011111111111111111111"
    vNumberData(6) = "111111111111111111111100000111111111100000001111111100111110011111100111111111111110011111111111111001000001111111100000000011111110001111100111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
    vNumberData(7) = "111111111111111111100000000001111110000000000111111001111110011111100111111001111111111111001111111111111100111111111111100111111111111100111111111111110011111111111111001111111111111100111111111111110011111111111111001111111111111111111111"
    vNumberData(8) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000111111110000000011111111001111001111111001111110011111100111111001111110011111100111111100000000111111111000000111111111111111111111"
    vNumberData(9) = "111111111111111111111000000111111111000000001111111001111110011111100111111001111110011111100111111100000000011111110000001001111111111111100111111111111110011111111111111001111110011111001111111100000000111111111000000111111111111111111111"

    ' 随机产生字符
    Dim vCode(), vCodes
    ReDim vCode(codeLen-1)
    vCodes = GetVerifyNumber
    For i = 0 To 4
        vCode(i) = cint(mid(vCodes,i+1,1))
        vCode(i) = pcd_doubter(vNumberData(vCode(i)),UnitWidth,UnitHeight,DotsLimit,tryCount,dbtTimes)
    Next

    ' 随机产生字符
    'Dim vCodes
    'ReDim vCode(codeLen-1)
    'For i = 0 To codeLen-1
    '  vCode(i) = Int(Rnd * cAmount)
    '  vCodes = vCodes & Mid(cCode, vCode(i) + 1, 1)
    '  vCode(i) = pcd_doubter(vNumberData(vCode(i)),UnitWidth,UnitHeight,DotsLimit,tryCount,dbtTimes)
    'Next

    'Session(pSN) = vCodes  '记录入Session

    ' 输出图像文件头
    Response.BinaryWrite ChrB(66) & ChrB(77) & Num2ChrB(54+ImgWidth*ImgHeight*3,4) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(54) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(40) & ChrB(0) & ChrB(0) & ChrB(0) & Num2ChrB(ImgWidth,4) & Num2ChrB(ImgHeight,4) & ChrB(1) & ChrB(0)

    ' 输出图像信息头
    Response.BinaryWrite ChrB(24) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & Num2ChrB(ImgWidth*ImgHeight*3,4) & ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0) & ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0)

    ' 生成干扰线
    ReDim noiseLine(1,-1)
    Call makeNoise(noiseLine,ImgWidth,ImgHeight)
    Call makeNoise(noiseLine,ImgWidth,ImgHeight)
    ' 如果想多画几条直接复制就可以
    ' Call makeNoise(noiseLine,ImgWidth,ImgHeight)

    ' 位置随机
    ActUnitWidth = Int(ImgWidth / codeLen)
    ImgYuWidth = ImgWidth - ActUnitWidth * codeLen
    ReDim posAry(1,codeLen-1)
    posAry(0,0) = Int((Rnd)*(posX+(ActUnitWidth-UnitWidth)/2))
    posAry(1,0) = Int((ImgHeight-UnitHeight)/2+(1-2*Rnd)*posY)
    For i=1 To codeLen-2
        posAry(0,i) = Int((1-2*Rnd)*(posX+(ActUnitWidth-UnitWidth)/2))
        posAry(1,i) = Int((ImgHeight-UnitHeight)/2+(1-2*Rnd)*posY)
    Next
    If codeLen > 1 Then
        posAry(0,codeLen-1) = Int((Rnd)*(posX+(ActUnitWidth-UnitWidth)/2))
        posAry(1,codeLen-1) = Int((ImgHeight-UnitHeight)/2+(-Rnd)*posY)
    End If

    ' 输出图像数据
    For i = ImgHeight-1 To 0 Step -1    '行
      For ii = 0 To codeLen-1                    '字
          For iii = 0 To ActUnitWidth-1         '字宽
              flag = 0
              If onNoiseLine(noiseLine,ii*ActUnitWidth+iii,i) Then ' 干扰线
                   flag = 1
            ElseIf getUnitDot(posAry,vCode,ii,iii,i,UnitWidth,UnitHeight) = "0" Then
                flag = 1
            ElseIf getUnitDot(posAry,vCode,ii-1,iii+ActUnitWidth,i,UnitWidth,UnitHeight) = "0" Then
                flag = 1
            ElseIf getUnitDot(posAry,vCode,ii+1,iii-ActUnitWidth,i,UnitWidth,UnitHeight) = "0" Then
                flag = 1
            End If
            ' 随机生成杂点
            If Rnd * 99 + 1 < cOdds Then flag = 1 - flag
            Response.BinaryWrite vColorData(1-flag)
             Next
        Next
         For ii = 0 To ImgYuWidth-1
             Response.BinaryWrite vColorData(1)
         Next
    Next
End Sub

Rem 获取单元的点(考虑位移)
Function getUnitDot(ByRef posAry,ByRef vCode,i,ByVal x,ByVal y,UnitWidth,UnitHeight)
    getUnitDot = "1"
    If i < 0 Or i > UBound(vCode) Then Exit Function
    x = x - posAry(0,i)
    If x < 0 Or x >= UnitWidth Then Exit Function
    y = y - posAry(1,i)
    If y < 0 Or y >= UnitHeight Then Exit Function
    getUnitDot = Mid(vCode(i),y*UnitWidth+x+1,1)
End Function

Rem 生成干扰线
Sub makeNoise(ByRef nl,imgW,UnitHeight)
    Dim i,l,x1,y1,x2,y2,dx,dy,deltaT
    x1 = Int(Rnd*imgW)
    y1 = Int(Rnd*UnitHeight)
    x2 = Int(Rnd*imgW)
    y2 = Int(Rnd*UnitHeight)
    dx = X2 - X1
    dy = Y2 - Y1
    If Abs(dx) > Abs(dy) Then deltaT = Abs(dx) Else deltaT = Abs(dy)
    If deltaT = 0 Then Exit Sub
    l = UBound(nl,2)
    ReDim Preserve nl(1,l+deltaT+1)
    l = l + 1
    For i = 0 To deltaT
        nl(0,l+i) = x1 + dx * i \ deltaT
        nl(1,l+i) = y1 + dy * i \ deltaT
    Next
End Sub

Rem 判断是否为干扰线上的点
Function onNoiseLine(ByRef nl,x,y)
    onNoiseLine = False
    Dim i
    For i=0 To UBound(nl,2)
        If x = nl(0,i) And y = nl(1,i) Then
            onNoiseLine = True
            Exit For
        End If
    Next
End Function

Rem 对单个字的点阵进行干扰
Rem 干扰思想:在点阵范围内随机产生2个端点,进行连线,以位移较大的一方做横轴,先将连线上的点删除,再将被删除点的纵轴方向上方或下方的点(随机确定)移向被删除点,移动后的空白用背景色补充
Function pcd_doubter(ByVal str,UnitWidth,UnitHeight,DotsLimit,tryCount,dbtTimes)
    Randomize
    Dim x1,x2,y1,y2,dx,dy,deltaT,i,ii,way,f1,f2
    For f1=1 To dbtTimes    '干扰次数
        For f2=1 To tryCount    '避免删除有效点超过上限的尝试次数限制
            '随机确定2个端点
            x1 = int(Rnd*UnitWidth)
            x2 = int(Rnd*UnitWidth)
            y1 = int(Rnd*UnitHeight)
            y2 = int(Rnd*UnitHeight)
            dx = X2 - X1
            dy = Y2 - Y1
            If Abs(dx) > Abs(dy) Then deltaT = Abs(dx) Else deltaT = Abs(dy)
            ReDim ary(1,deltaT)    '存储连线的点
            If deltaT = 0 Then
                ary(0,0) = x1
                ary(1,0) = y1
            Else
                ii = 0
                For i = 0 To deltaT
                    ary(0,i) = x1 + dx * i \ deltaT
                    ary(1,i) = y1 + dy * i \ deltaT
                    If pcd_getDot(ary(0,i),ary(1,i),str,UnitWidth) = "0" Then ii = ii + 1
                Next
                ' 统计连线上有效点的数量,如未超过有效点上限则跳出循环,执行干扰
                If ii <= DotsLimit Then Exit For
            End If
        Next

        ' 执行干扰(dx,dy改作不同的方向标记用)
        If Abs(dx) > Abs(dy) Then dx = 1 Else dx = 0
        If dx = 1 Then
            If Int(Rnd*10) > 4 Then
                dy = 1
                way = -1
            Else
                dy = UnitHeight - 2
                way = 1
            End If
        Else
            If Int(Rnd*10) > 4 Then
                dy = 1
                way = -1
            Else
                dy = UnitWidth - 2
                way = 1
            End If
        End If
        For i=0 To deltaT
            For ii=ary(dx,i) To dy Step way
                Call pcd_setDot(ary(0,i)*dx+ii*(1-dx),ary(1,i)*(1-dx)+ii*(dx),str,pcd_getDot(ary(0,i)*dx+(ii+way)*(1-dx),ary(1,i)*(1-dx)+(ii+way)*(dx),str,UnitWidth),UnitWidth)
            Next
            '添补空白
            Call pcd_setDot(ary(0,i)*dx+(dy+way)*(1-dx),ary(1,i)*(1-dx)+(dy+way)*(dx),str,"1",UnitWidth)
        Next
    Next
    pcd_doubter = str
End Function

Rem 得到某点的字符
Function pcd_getDot(x,y,str,UnitWidth)
    pcd_getDot = Mid(str,x+1+y*UnitWidth,1)
End Function

Rem 设置某点的字符
Sub pcd_setDot(x,y,ByRef str,newDot,UnitWidth)
    str = Left(str,x+y*UnitWidth) & newDot & Right(str,Len(str)-x-y*UnitWidth-1)
End Sub

Rem 将数字转为bmp需要的格式 lens是目标字节长度
Function Num2ChrB(ByVal num,lens)
    Dim ret,i
    ret = ""
    While (num>0)
        ret = ret & ChrB(num mod 256)
        num = num \ 256
    WEnd
    For i=Lenb(ret) To lens-1
        ret = ret & chrB(0)
    Next
    Num2ChrB = ret
End Function
%>


  • 上一条:
    错误类型:Provider (0x80004005)未指定的错误 的一个处理方法
    下一条:
    解决采集时出现msxml3.dll 错误的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 国外服务器实现api.openai.com反代nginx配置(0个评论)
    • 2024/4/28最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客