问题的提出:
我们正在开发一个较大的工程,为了分工也为了模块清晰,工程分了多个模块。但整个工程是需要登录来确认身份,并且根据身份确定登录这的权限。当然,不能为每个模块都开发一个登录界面,我们希望通过一个程序控制所有程序。
思路:
建立一个login.dll,它来实现登录功能,并且它提供一个界面,该界面能够连接到各个模块,当然,参数也传递过去。而各个模块只有得到正确的参数(userid和password)才能正确执行。
问题:
1、参数如何传递
2、参数如何不在客户端出现
3、各个模块如何调试
一、建立login.dll
一.1 ServerController内容:
unit ServerController;
{PUBDIST}
interface
uses
Classes,
DatamoduleUnit,
IWServerControllerBase, IWAppForm, IWApplication,
SysUtils;
type
TIWServerController = class(TIWServerControllerBase)
procedure IWServerControllerBaseNewSession(ASession: TIWApplication;
var VMainForm: TIWAppForm);
procedure IWServerControllerBaseCreate(Sender: TObject);
private
public
end;
TUserSession = class(TComponent)
public
datamodule1:Tdatamodule1;
user_id,user_name:string;
constructor Create(AOwner: TComponent); override;
destructor destroy; override;
function check_user(u_id,u_pwd:string):boolean;
end;
function UserSession: TUserSession;
//自定义的几个函数和过程
function cut_it(s:string):string;
procedure movetoDLL(DLLName:string;frm:TIWAppForm);
procedure movetoDLLAnonym(DLLName:string;frm:TIWAppForm);
function DLL2longURL(DLLName:string):string;
function DLL2longURLWithUser(DLLName:string):string;
implementation
{$R *.dfm}
uses
IWInit,Registry,StrUtils,login_mainIWU;
function DLL2longURL(DLLName:string):string;
begin
result:='http://'+RWebApplication.Request.Host+'/'+cut_it(RWebApplication.URLBase)+DLLName;
end;
function DLL2longURLWithUser(DLLName:string):string;
begin
result:=DLL2longURL(DLLName)+'?userid='+UserSession.user_id+'&password='+UserSession.user_pwd;
end;
function cut_it(s:string):string;
var i,j:integer;
begin
i:=pos('/',s);
while i>0 do begin
j:=i;
i:=posEx('/',s,i+1);
end;
result:=copy(s,1,j);
end;
procedure movetoDLL(DLLName:string;frm:TIWAppForm);
begin
frm.addtoinitproc('window.open("'+DLL2longURLWithUser(DLLName)+'","","");')
end;
procedure movetoDLLAnonym(DLLName:string;frm:TIWAppForm);
begin
frm.addtoinitproc('window.open("'+DLL2longURL(DLLName)+'","","");')
end;
function UserSession: TUserSession;
begin
Result := TUserSession(RWebApplication.Data);
end;
{ TUserSession }
constructor TUserSession.Create(AOwner: TComponent);
begin
inherited;
datamodule1:=Tdatamodule1.Create(AOwner);
end;
destructor TUserSession.destroy;
begin
inherited ;
end;
function TUserSession.check_user(u_id,u_pwd:string):boolean;
begin
result:=true;
end;
procedure TIWServerController.IWServerControllerBaseNewSession(
ASession: TIWApplication; var VMainForm: TIWAppForm);
begin
ASession.Data := TUserSession.Create(ASession);
end;
end.
这个单元没有特别需要说明的,其中的check_user是示意性质的,填上实际的代码即可。
这个单元里定义了几个全局函数和过程,以便其他地方调用。
一.2 登录窗口(单元)内容,略。
一.3 主窗口。当登录成功后,显示这个窗口,通过该窗口可以连接到其他模块。
这个窗口唯一要说明的是如何连接到其他模块,请看其中一个连接的代码:
procedure TFrmTop.IWLinkTestClick(Sender: TObject);
begin
movetodll('test.dll',RWebApplication.ActiveForm as TIWAPPForm)
end;
其中 movetodll在ServerController单元里已经定义过了。系统假设test.dll与login.dll放在同一个目录下。
二、建立其他模块
我们知道login.dll已经将参数传递过来,在其他模块里如何接收?看看其他模块的ServerController单元就明白了:
unit ServerController;
{PUBDIST}
interface
uses
Classes,
DatamoduleUnit,
IWServerControllerBase, IWAppForm, IWApplication,
SysUtils;
type
TIWServerController = class(TIWServerControllerBase)
procedure IWServerControllerBaseNewSession(ASession: TIWApplication;
var VMainForm: TIWAppForm);
procedure IWServerControllerBaseCreate(Sender: TObject);
private
public
end;
TUserSession = class(TComponent)
public
datamodule1:Tdatamodule1;
user_id,user_name:string;
//
constructor Create(AOwner: TComponent); override;
function check_user(u_id,u_pwd:string):boolean;
end;
function UserSession: TUserSession;
implementation
{$R *.dfm}
uses
IWInit,Registry,StrUtils;
constructor TUserSession.Create(AOwner: TComponent);
begin
inherited;
datamodule1:=Tdatamodule1.Create(AOwner);
end;
function TUserSession.check_user(u_id,u_pwd:string):boolean;
begin
result:=false;
//你的代码
result:=true;
end;
procedure TIWServerController.IWServerControllerBaseNewSession(
ASession: TIWApplication; var VMainForm: TIWAppForm);
var userid,pwd:string;
begin
ASession.Data := TUserSession.Create(ASession);
with ASession.RunParams do begin
userid:=Values['userid'];
pwd:=Values['password'] ;
end;
//userid:='0';pwd:='111111'; //请注意!!!调试时使用!!!
with usersession do
if (userid='') or(not check_user(userid,pwd)) then
ASession.Terminate('对不起,你没有这个权限。');
end;
end.
当创建一个新的session的时候,要判断是否有参数过来,如果没有参数,或者有参数但不被许可,那么“对不起,你没有这个权限。”。
本例中,每个模块都有自己的check_user,也许你不需要这样。
现在,每个模块都已经得到了传过来的口令和密码了,进一步的工作就是你自己的事情了。
但是,事情并没有就此结束,传递过来的参数会显示在客户端。这是不能接受的。我也在等待更好的解决办法,但在更好的解决办法出现之前,还用我原来的方法吧——这个方法我在别处说过:
在各个模块的主窗口的javascript属性里加上这样的代码:
var str=location.href;
pos=str.indexOf("?");
if (pos>=0) {
location=str.substring(0,pos);
}
可以看出,代码在客户端将参数截去了,这导致页面更新了一次,这也不算什么问题,因为仅仅多访问一次服务器而已。不过,客户端会跳出一个警告框,这很烦。去掉这个警告框很容易,只要将IWServerController的showResyncWarning置成false即可。
还要提醒一下:login.dll里使用的参数名称必须跟其他模块使用的参数名称一样,事先要约定好。
到这里应该说大功告成了。下面是“完美主义者”的讨论:
1、客户端真的看不到参数了吗?其实,既然带参数的url成功的访问了服务器,ie的下拉框里难免会留下痕迹。怎么办?两个思路:
A 你告诉浏览器:不要保存我的url。至于怎样“告诉”,我也不会!
B 口令加密,即使看到又如何?
2、其他模块如何调试?平时,我都是通过另一个产生exe的工程来调试,我想你也是。但程序需要参数,怎么办?看到上面代码中的注释了吗?这一行就是用来调试的。当然,你在浏览器中,输入url时手工添加参数也行。
to powersite :呵呵,这是别人的东东.你看有没有用.
顺便问一个问题.
我用intraweb application wizard 做一小程序.
运行时在IE页面有时会出现如下错误信息,如何解决,
No main form is defined.
在线候教.