1. 程式人生 > >使用kbmmw 實現圖形驗證碼

使用kbmmw 實現圖形驗證碼

null -c classes rst 字符 bit verify round span

首先感謝圖形驗證碼的提供者 晴空無彩虹 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;
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];

                vcode:=vcodelist.BeginRead.Values[m];

                vcodelist.EndRead;

      finally
      vl.Free

      end;

    if invcode=vcode then
       result:=驗證通過!;
     
end;

新建一個HTML 文件 叫 vcodetest.html

<script language="javascript" id="clientEventHandlersJS">
 function B1_onclick() {
 
 if (document.form1.vcode.value==""){
     alert("驗證碼不能為空!");
     document.form1.vcode.focus();
     return false
      }    
  }      
 
</script>
 
<form name="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="提交" onClick="return B1_onclick()">        
      <input type="reset" name="Submit" value="重置">
    </td>

運行。

瀏覽器裏面輸入 http://127.0.0.1/xalionrest/vcodetest.html

技術分享圖片

輸入驗證嗎,點提交。

技術分享圖片

大年初二,祝大家在豬年,萬事如意,大吉大利!

使用kbmmw 實現圖形驗證碼