红鱼儿

kbmMW User authentication

任何信息系统的一个非常重要的部分是能够对用户进行身份验证。 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.

 

posted on 2018-08-12 20:42  红鱼儿  阅读(408)  评论(0编辑  收藏  举报