使用kbmmw 实现图形验证码
Posted xalion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用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;
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 实现图形验证码的主要内容,如果未能解决你的问题,请参考以下文章