任何信息系统的一个非常重要的部分是能够对用户进行身份验证。 kbmMW在这里提供了非常强大的机制。 TkbmMWSimpleClient提供简单的用户身份验证机制,您可以在连接到应用程序服务器时传递UserName和Password。 但是,要创建最灵活和最强大的身份验证机制,有必要编写一些代码......这里的标准方法是使用令牌(tokens)来验证客户端请求,这样用户名和密码就不会在所有客户端请求上传递,这种方式是更安全的。
服务器生成令牌而不是客户端。 客户只是接收回传的内容。 您可以使用clientident.customdata来存储用户的id,但是您也可以使用它来返回在“perm”中定义的内容。 我认为这种方法更好,所以看下面的代码:
unit Unit11; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Data.DB, kbmMWServer, kbmMemTable, kbmMWSecurity, kbmMWExceptions,kbmMWuniDAC, DBAccess, Uni, kbmMWCustomConnectionPool; type TForm11 = class(TForm) mwServer: TkbmMWServer; Memo1: TMemo; tbmusers: TkbmMemTable; mwcpool: TkbmMWUNIDACConnectionPool; UniConnection1: TUniConnection; procedure mwServerAuthenticate(Sender: TObject; ClientIdent: TkbmMWClientIdentity; var Perm: TkbmMWAccessPermissions; var AMessage: string); private function IsUserLegit(UserName,password:string;var customdata,token:string):Boolean; function IsTokenLegit(token:string):Boolean; public { Public declarations } end; var Form11: TForm11; implementation {$R *.dfm} function TForm11.IsTokenLegit(token: string): Boolean; begin tbmusers.Lock; try if tbmusers.Locate('token',token,[]) then begin Result:=true; tbmusers.Edit; tbmusers.FieldByName('exppiry').AsDateTime:=Now+(15/(60*24));//当前时间+15分钟 tbmusers.Post; end else Result:=false; finally tbmusers.Unlock; end; end; function TForm11.IsUserLegit(UserName, password: string; var customdata, token: string): Boolean; var conn:TkbmMWUNIDACConnection; qry:TUniQuery; begin Result := False; qry := TUniQuery.Create(nil); conn := TkbmMWUNIDACConnection(mwcpool.GetBestConnection(true, -1, nil, 180)); try qry.Connection := conn.Database; qry.SQL.Add('select id from employees where name=:username and password=:password'); qry.ParamByName('username').AsString := UserName; qry.ParamByName('password').AsString := password; qry.Open; if qry.Eof then begin Result := False;//用户名或密码错误 end else begin //用户与密码正确,建立token并返回customdata. customdata := qry.Fields[0].AsString; //建立简单的token token := customdata + IntToStr(GetTickCount); Result := True; end; finally FreeAndNil(qry); FreeAndNil(conn); end; end; procedure TForm11.mwServerAuthenticate(Sender: TObject; ClientIdent: TkbmMWClientIdentity; var Perm: TkbmMWAccessPermissions; var AMessage: string); var userdata, token: string; begin // no access by default perm:=[]; //check to see if user already logged in if clientident.token='' then begin memo1.lines.add(clientident.password); if IsUserLegit(clientident.username,clientident.password,userdata,token) then begin clientident.Data:=userdata; clientident.Token:=token; perm:=[mwapRead, mwapWrite, mwapDelete, mwapExecute]; try tbmusers.Lock; tbmusers.Insert; tbmusers.FieldByName('id').AsString:=userdata; tbmusers.FieldByName('token').AsString:=token; tbmusers.FieldByName('expiry').AsDateTime:=now+(15/(60*24)); tbmusers.Post; finally tbmusers.Unlock; end; end else raise EkbmMWAuthException.Create(1,'Username or Password Invalid'); end else begin if IsTokenLegit(clientident.token) then perm:=[mwapRead, mwapWrite, mwapDelete, mwapExecute] else raise EkbmMWAuthException.Create(2,'Timeout'); end; clientident.Username:=''; clientident.Password:=''; end; end.