前面hawkfly提到的在多层编程中,服务器端安全性验证的问题
7 R. P4 R* M2 M. {# k: v6 c1 e在以socket方式实现MIDAS时尤为明显,DCOM/CORBA都有现成的
安全管理功能,而socket方式在这方面比较薄弱,没有现成的解决方案
现就我以前对MIDAS编程的理解,做一个简要的介绍,
" {" B8 F, V9 p: Y& R5 y$ V/ B/ q以后有时间精力再详细举例说明
win2k中dcom的安全级别有7种,其中
$ @1 c* J5 w N. c/ b u) j" V最低的“无”安全检查暂且不论
默认的“身份验证”服务方式几句话也说不清,
6 M: l8 H: q! y& `6 q( Q先放到一边,看看剩下的5种
* S& }* ]1 V" H- H
1.连接,仅对初始连接进行安全检查
因为tcp/ip是稳固的连接,因此每个连接,也就是每个RemoteDataModule
3 P8 Z& j2 ]) k7 ]9 P9 ]8 a1 B实例检测一次即可,实现方法很多,这里简要介绍一种最简单的
) l9 n2 [& C s8 K9 z! D可以在服务器端的TypeLibrary里面为你的服务器接口增加若干个方法,如
/ y6 d0 K: v, f$ g7 n- {* sinterface ILoginServer: IAppServer
2 a) j0 T2 N6 `* A/ g{
* _0 C$ C5 A/ c4 {! k' M8 a+ p[
id(0x00000001)
- e/ Q& ?& F$ ?]
0 `; w8 R1 J, p! nHRESULT _stdcall Login( void );
$ e! H o% X/ F# l& k8 K V. J[
0 o; e) ^2 {+ oid(0x00000002)
]
HRESULT _stdcall Logout( void );
};
& S* H6 p0 P4 {5 i. |在方法中实现你的客户身份校验,而在校验之前,通过把RDM上所有的TDataSetProvider
3 c4 }& \0 N0 d" D1 Z! H7 H! @1 j的Exported属性关掉即可让客户端无法看到服务器端的provider
因为客户端实际上是在连接服务器成功后通过服务器之IAppServer接口访问
所有的Provider,如IAppServer::AS_GetProviderNames可以取得
服务器端所有exported的IProvider接口名称,而所有数据的取得、修改
9 g* ?3 H3 o7 o& |; E1 U* z都是通过相应的ProviderName来指定的,如
virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in
+ b9 R) G; M* Lt Count, int &RecsOut, int Options, const WideString: CommandText, OleVarian
t &
arams, OleVariant: &OwnerData, OleVariant &GetRecords_result) = 0 ;
取得数据方法的第一个参数就是你需要操作的数据集名称……
/ h3 n' E7 i, J如果你把服务器RDM上所有的TDataSetProvider::Exported关掉,
# T( a/ }; t( ]4 v7 h则客户端看不到任何Provider,也无法通过其ProviderName取得数据
例如我在服务器端的RDM类中加入
. C' b4 L! M; i; D- }: l8 Nclass TLoginServer : public TCRemoteDataModule
{
4 A7 T3 F% {- h' R...
0 q) G- f( h8 O3 y3 @% u4 r5 cprivate: // User declarations
bool FLogin;
void __fastcall SetLogin(bool value);
bool __fastcall IsLogin(OleVariant &OwnerData);
...
__published:
__property bool Login = { read = FLogin, write = SetLogin };
};
在RDM实现类中
+ e: W9 y6 _( A9 Wclass ATL_NO_VTABLE TLoginServerImpl: 。。。
) Z1 ]. m4 ` W# z# ?5 s4 c# _{
// ILoginServer
0 v/ e- P4 u/ [/ Y$ N$ Jprotected:
4 x5 c, Y1 _9 T- N$ D' a+ j( m0 YSTDMETHOD(Login());
STDMETHOD(Logout());
% a) t2 H9 M5 v2 Q* z5 `/ Y- I};
6 e- q( i0 h$ t$ T然后简单实现之
4 r& `, ?5 w4 Z( G__fastcall TLoginServer::TLoginServer(TComponent* Owner)
8 f. @0 d, N- w: TCRemoteDataModule(Owner), FLogin(false)
{
}
: T! d$ M. b; p//---------------------------------------------------------------------------
; |* G( f- r' [7 J/ Q5 Jvoid __fastcall TLoginServer::SetLogin(bool value)
0 U# \7 \# @/ F! O$ e5 c{
if(FLogin != value)
{
/ s6 ?9 C* \# {3 eFLogin = value;
) }5 `2 O* x$ V! d% HdspAnimals->Exported = FLogin;
}
; O, G1 ~/ U, h8 ?; k- ^- M) k}
//---------------------------------------------------------------------------
STDMETHODIMP TLoginServerImpl:
ogin()
{
m_DataModule->Login = true;
7 W" c* u! s) \2 yreturn S_OK;
}
//---------------------------------------------------------------------------
# D) @% n# v5 E, I( gSTDMETHODIMP TLoginServerImpl:
ogout()
{
m_DataModule->Login = false;
, R+ i$ A. A7 Z, r, I9 Y2 p, w! E8 Sreturn S_FALSE;
& a9 ~: x+ Y$ t' f: r4 K1 c}
" h( `% G( Y0 |0 o. }$ j//---------------------------------------------------------------------------
3 ~! `; f" q2 o: o( Z# Abool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)
6 h& y% i7 T* E; I{
& h3 C6 I6 g+ M; w: X4 Xreturn FLogin;
}
. q+ p* |6 D; b' L2 Reasy
这样除非你的客户端成功调用Login方法,否则他是无法使用
dspAnimals这个数据集Provider的,成功调用后手工打开的数据集使用完全相同
比如客户端可以用如下代码
( m f# b. g9 dIDispatch *dispAppServer = (IDispatch*)(DM->Connection->AppServer);
ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;
dispLoginServer.Login();
DM->cdsAnimals->Open();
; ]3 K8 @( S" |$ Y" l" w$ A0 m实现注册,并且打开相应数据集……
5 A9 L& \7 y# Y/ H
因为大多数的三层程序对安全性要求并不高,因此这样的安全检测对
) @- e5 b: _8 W& b4 E B ^绝大多数程序应该足以……
| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |