使用kbmmw 實現圖形驗證碼

首先感謝圖形驗證碼的提供者    https://blog.csdn.net/u011784006/article/details/80827181javascript

他用FMX 實現了驗證碼的生成,我修改爲了 VCL 版的。html

整個生成驗證碼的單元,全程推出。java

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 裏面實現兩個過程,一個過程是生成隨機驗證圖片,並保存驗證碼在內存中。另一個過程就是jquery

驗證瀏覽器輸入的驗證碼。本篇文章主要是討論功能實現,請你們在實際應用中進一步完善,保證信息和數據安全。vim

[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.htmlcookie

輸入驗證嗎,點提交。app

 

大年初二,祝你們在豬年,萬事如意,大吉大利!dom

 

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

相關文章
相關標籤/搜索