zoukankan      html  css  js  c++  java
  • 使用kbmmw 实现图形验证码

    首先感谢图形验证码的提供者    https://blog.csdn.net/u011784006/article/details/80827181

    他用FMX 实现了验证码的生成,我修改成了 VCL 版的。

    整个生成验证码的单元,全程推出。

    unit uVerifyCode;
    
    interface
    
    uses System.Classes, System.SysUtils,vcl.graphics,Vcl.ExtCtrls, System.IOUtils,
      System.UIConsts, System.UITypes,  kbmMWGlobal,   jpeg,
      System.Types;
    // 本单元修改自 晴空无彩虹 的单元,表示感谢
    type
      // 生成验证码组件
      TGenerateVerifyCode = class
      private const
        // 定义字典表,不要零(0),因为零和字母O样子太接近
         arrStr: array [0 .. 34] of char = (
          '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');
      private
        FBitmapWidth: integer; // 图片宽度
        FBitmapHeight: integer; // 图片高度
        FCodeCount: integer; // 取验证码字符的个数,默认是4个字符
        FFontName: string; // 字体名称
        FMinFontSize: integer; // 最小字体大小
        FRandomLineCount: integer; // 背景随机线条数
        FTransparency: byte; // 背景随机线条的透明度
        FXRandomLen: integer; // X的随机值长度
        FYRandomLen: integer; // Y的随机值长度
        FLock:TkbmMWLock;
        // 画出验证码函数
        function VerifyCodeDrawImg(Img:TBitmap): string;
      public
        constructor Create();
        destructor Destroy;override;
        procedure GetVerifyCodeAndImage(ImageStream: TStream;
          var VerifyCode: string);
    
        property Width: integer read FBitmapWidth write FBitmapWidth;
        property Height: integer read FBitmapHeight write FBitmapHeight;
        property CodeCount: integer read FCodeCount write FCodeCount;
        property FontName: string read FFontName write FFontName;
        property MinFontSize: integer read FMinFontSize write FMinFontSize;
        property RandomLineCount: integer read FRandomLineCount
          write FRandomLineCount;
        property Transparency: byte read FTransparency write FTransparency;
        property XRandomLen: integer read FXRandomLen write FXRandomLen;
        property YRandomLen: integer read FYRandomLen write FYRandomLen;
      end;
    
    
    function GetVerifyCodeAndImage( ImageStream: TStream):string;
    
    implementation
    
    
    
    function GetVerifyCodeAndImage( ImageStream: TStream):string;
    var
      gc:TGenerateVerifyCode;
    begin
       gc:=TGenerateVerifyCode.Create;
       try
        gc.GetVerifyCodeAndImage(ImageStream, result);
        ImageStream.Position:=0;
    
       finally
         gc.Free;
       end;
    
    end;
    
    constructor TGenerateVerifyCode.Create();
    begin
      inherited;
      FBitmapWidth := 200;
      FBitmapHeight := 60;
      FCodeCount := 4;
      FFontName := '宋体';
      FMinFontSize := 15;
      FRandomLineCount := 100;
      FTransparency := 200;
      FXRandomLen := 10;
      FYRandomLen := 8;
       FLock:=TkbmMWLock.Create;
    
    end;
    
    // 获取验证码和影像的流数据
    destructor TGenerateVerifyCode.Destroy;
    begin
          FLock.Free;
         inherited;
    end;
    
    procedure TGenerateVerifyCode.GetVerifyCodeAndImage(ImageStream: TStream;
      var VerifyCode: string);
    var
      Img: TBitmap;
      jpg:TJPEGImage;
    begin
    
      Img :=TBitmap.Create;
       jpg:=TJPEGImage.Create;
      try
        Img.Width:=FBitmapWidth;
        img.Height:=FBitmapHeight;
        // 宽200,高60
    
        VerifyCode := VerifyCodeDrawImg(Img);
        jpg.Assign(img);
        jpg.SaveToStream(ImageStream);
        ImageStream.Position:=0;
        Img.SaveToStream(ImageStream); // 写到流中
      finally
    
        freeandnil(Img);
        freeandnil(jpg);
      end;
     
    end;
    
    // 画出验证码函数
    function TGenerateVerifyCode.VerifyCodeDrawImg(Img: TBitmap): string;
    var
      I, j, k: integer;
      X, Y, W, H: integer;
      vLeft: integer;
      strResult,c,fn:  String;
      myrect:Trect;
    begin
      // 只取4个字符
      fn:=Tpath.GetGUIDFileName;
      For j := 1 to FCodeCount do
      begin
        Randomize;
        k := Random(1000000) mod 35;
        strResult := strResult + trim(arrStr[k]);
      end;
    
      img.Canvas.Brush.Style:= bsSolid;
      img.Canvas.Brush.Color:=AlphaColorToColor( MakeColor(Random(256) and $C0,Random(256) and $C0, Random(256) and $C0 , FTransparency));
      img.Canvas.FillRect(TRect.Create(0, 0,FBitmapWidth, FBitmapHeight) );
    
      sleep(1);
    
      Img.Canvas.Font.Name := FFontName;
    
      for j := 1 to FRandomLineCount do // 随机画100条线
      begin
        Randomize;
    
        Img.Canvas.Pen.Color :=AlphaColorToColor( MakeColor(Random(256) and $C0,Random(256) and $C0, Random(256) and $C0 , FTransparency));
        Img.Canvas.Pen.Width:=2;
    
        Img.Canvas.PenPos.SetLocation(Random(FBitmapWidth),Random(FBitmapHeight));
        Img.Canvas.LineTo(Random(FBitmapWidth), Random(FBitmapHeight));
        // 1
      end;
    
    
      vLeft := 5;
      for I := 1 to length(strResult) do
      begin
        Randomize;
        // 字体大小
        Img.Canvas.Font.Size := Random(16) + FMinFontSize;
        // 随机字体颜色
         Img.Canvas.Font.Color:= AlphaColorToColor( MakeColor(Random(256) and $C0,Random(256) and $C0, Random(256) and $C0 , FTransparency));
        if Img.Canvas.Font.Size < (FMinFontSize + 10) then
          Img.Canvas.Font.Size := Img.Canvas.Font.Size +10;
        if Random(2) = 1 then
          Img.Canvas.Font.Style := [TFontStyle.fsBold]
        else
          Img.Canvas.Font.Style := [TFontStyle.fsItalic];
         Img.Canvas.Font.Style:=Img.Canvas.Font.Style+[fsStrikeOut];
    // 背景色反色
        img.Canvas.Brush.Color:=Img.Canvas.Font.Color xor $FFFFFF;//  AlphaColorToColor( MakeColor(Random(256) and $C0,Random(256) and $C0, Random(256) and $C0 , FTransparency));
        Img.Canvas.Brush.Style:=bsSolid;
        begin
          X := Random(FXRandomLen) + vLeft;
          Y := Random(FYRandomLen);
          W := Img.Canvas.TextWidth(strResult[I])+20;
          H := Img.Canvas.TextHeight(strResult[I]);
          myrect:=TRect.Create(X, Y, X + W, Y + H);
          c:=strResult[i];
          Img.Canvas.TextRect(myrect,c,[tfCenter] );
          vLeft := X + W + 1;
        end;
      end;
    
    
      for j := 1 to 5 do // 随机画5条线
      begin
        Randomize;
    
        Img.Canvas.Pen.Color :=AlphaColorToColor( MakeColor(Random(256) and $C0,Random(256) and $C0, Random(256) and $C0 , FTransparency));
        Img.Canvas.Pen.Width:=1;
     
        Img.Canvas.PenPos.SetLocation(Random(FBitmapWidth),Random(FBitmapHeight));
        Img.Canvas.LineTo(Random(FBitmapWidth), Random(FBitmapHeight));
        // 1
      end;
    
    
      Result := strResult; // 返回值
    end;
    
    end.

    好了,我们下面在kbmmw 里面实现两个过程,一个过程是生成随机验证图片,并保存验证码在内存中。另外一个过程就是

    验证浏览器输入的验证码。本篇文章主要是讨论功能实现,请大家在实际应用中进一步完善,保证信息和数据安全。

    [kbmMW_Rest('method:get, path:"getvimage", responseMimeType:"image/jpeg"')]
         [kbmMW_Method]
         function Getvimage:TkbmMWBytes;
    var
    vcodelist:TkbmMWThreadDictionary<string,string>;


    function TkbmMWCustomHTTPSmartService1.Getvimage: TkbmMWBytes;
    var
      imgs,js:Tmemorystream;
      vcode:string;
      hlp,reshlp:TkbmMWRESTTransportStreamHelper;
      cookie:TkbmMWHTTPCookie;
      stoken:string;
    begin
        hlp:=TkbmMWRESTTransportStreamHelper(RequestTransportStream.Helper);
        imgs:=Tmemorystream.create;
       try
          vcode:=GetVerifyCodeAndImage(imgs);
          Result:=TkbmMWPlatformMarshal.Stream2Bytes(imgs);
          stoken:=THashmd5.GetHashString(TkbmMWMixerPasswordGen.Make);
          cookie:=TkbmMWHTTPCookie.Create;
          cookie.Name:='vcode';
          cookie.Value:=stoken;
          cookie.Expires:=Tkbmmwdatetime.Null;
          reshlp:=TkbmMWRESTTransportStreamHelper(ResponseTransportStream.Helper);
          reshlp.Cookies.Add(cookie);
           vcodelist.Add(stoken,vcode); finally
             imgs.free;
    
        end;
    
    end;
     [kbmMW_Rest('method:post, path:"vcodetest", responseMimeType:"text/html"')]
         [kbmMW_Method]
         function vcodetest:string;
    function TkbmMWCustomHTTPSmartService1.vcodetest: string;
    var
       hlp:TkbmMWRESTTransportStreamHelper;
        vl:TkbmMWHTTPCustomValues;
       m,invcode,vcode:string;
       p:Tbytes;
    begin
    
       result:='验证失败!';
    
    
    
        hlp:=TkbmMWRESTTransportStreamHelper(RequestTransportStream.Helper);
    
        m:= hlp.Cookies.ValueByName['vcode'];
    
        if m='' then exit;
        
    
         vl:=TkbmMWHTTPQueryValues.Create;
          try
    
                    p:= RequestStream.SaveToBytes;
    
                    vl.AsString:= Tencoding.ASCII.GetString(p);
    
                    invcode:= vl.ValueByName['vcode'];
    
                    if not vcodelist.TryGetValue(m,vcode) then
                      vcode:='';
    finally vl.Free end; if invcode=vcode then result:='验证通过!'; end;

    新建一个HTML 文件 叫 vcodetest.html

    <script type="text/javascript" src="/xalionrest/scripts/jquery-1.12.4.min.js"></script>  
    <script language="javascript" >
    $().ready(function(){
    $("#img-code").bind( 'click', function () {
            $(this).attr('src','/xalionrest/getvimage?t='+Math.random());
            });
            
    $("#form1").submit(function(){
    
        if ($("input[name='vcode']").val() == ""){
     
        alert("验证码不能为空!");
     
        $("input[name='vcode']").focus();
     
        return false
     
           }    
           });
           
    
    });    
    </script>
    <form name="form1"  id="form1" method="post" action="/xalionrest/vcodetest" enctype="application/x-www-form-urlencoded" >
      <tr>
        <td align="center">
               <span class="style2">输入验证码</span><input name="vcode" type="text" id="vcode">
               <img src="/xalionrest/getvimage" height=60 width=200  id="img-code" class="Verify-Code" style="cursor:pointer" alt="验证码" title="看不清楚?请刷新">
            
         </td>
      </tr>
      
      <tr>
    
        <td align="center">
          <br>
          <input type="submit" name="Submit" value="提交" >        
          <input type="reset" name="Submit" value="重置">
        </td>
      </tr>
     </form> 

    运行。

    浏览器里面输入 http://127.0.0.1/xalionrest/vcodetest.html

    输入验证吗,点提交。

    大年初二,祝大家在猪年,万事如意,大吉大利!

    2019.5.18 update :使用了kbmmw 5.09中新加的 TkbmMWThreadDictionary<string,string> 处理 键值,效果更好,更方便。

  • 相关阅读:
    在线教程-Qt参考文档
    利用QT中Qpainter画点,直线,弧线等简单图形
    Office2013下载地址
    Linux下声卡的安装(ALSA)
    聆听自由的声音----Linux下声卡驱动软件ALSA的安装与配置
    linux找回root密码
    删除排序数组中重复的元素【数组专题】
    类模板派生出新的类模板
    TCP的拥塞控制
    linux运行级别
  • 原文地址:https://www.cnblogs.com/xalion/p/10353535.html
Copyright © 2011-2022 走看看