/ t* O0 L1 d- c0 F) L+ Y1 ?
前面hawkfly提到的在多层编程中,服务器端安全性验证的问题
! x7 z3 V& p/ X/ _/ B在以socket方式实现MIDAS时尤为明显,DCOM/CORBA都有现成的
安全管理功能,而socket方式在这方面比较薄弱,没有现成的解决方案
" E! B% u' D* F9 k& t现就我以前对MIDAS编程的理解,做一个简要的介绍,
以后有时间精力再详细举例说明
win2k中dcom的安全级别有7种,其中
最低的“无”安全检查暂且不论
默认的“身份验证”服务方式几句话也说不清,
' U, K2 s" e' B V先放到一边,看看剩下的5种
4 T# A7 s; m. _; t$ J
1.连接,仅对初始连接进行安全检查
' T8 Q) y; z) O5 h D. P; {( @
因为tcp/ip是稳固的连接,因此每个连接,也就是每个RemoteDataModule
实例检测一次即可,实现方法很多,这里简要介绍一种最简单的
^1 H- T% y* i L0 p/ e4 w可以在服务器端的TypeLibrary里面为你的服务器接口增加若干个方法,如
interface ILoginServer: IAppServer
{
[
id(0x00000001)
- L7 v: J) G) J3 u]
HRESULT _stdcall Login( void );
7 ^! f! u) ]$ c' w/ ?5 D6 U/ I) `' s[
2 M% U% Y2 F6 h1 eid(0x00000002)
+ t' `9 X/ D8 Q+ g, E]
0 _2 d q) Z1 L% ZHRESULT _stdcall Logout( void );
};
在方法中实现你的客户身份校验,而在校验之前,通过把RDM上所有的TDataSetProvider
# M1 B' ^8 ]+ V3 `- o的Exported属性关掉即可让客户端无法看到服务器端的provider
因为客户端实际上是在连接服务器成功后通过服务器之IAppServer接口访问
: e9 y0 Q% N- I所有的Provider,如IAppServer::AS_GetProviderNames可以取得
服务器端所有exported的IProvider接口名称,而所有数据的取得、修改
) G! t. w( J: h6 ]- Y( y都是通过相应的ProviderName来指定的,如
! I5 W h, R) x0 G% k2 c+ I4 E2 Wvirtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in
0 i7 I& S3 t3 {t Count, int &RecsOut, int Options, const WideString: CommandText, OleVarian
t &
arams, OleVariant: &OwnerData, OleVariant &GetRecords_result) = 0 ;
取得数据方法的第一个参数就是你需要操作的数据集名称……
4 S( e) j% {4 m如果你把服务器RDM上所有的TDataSetProvider::Exported关掉,
则客户端看不到任何Provider,也无法通过其ProviderName取得数据
2 c; m) K/ C; b- x* d( `. T例如我在服务器端的RDM类中加入
# L6 j7 C" Q$ \5 M, L6 y/ `) Y2 ]7 Aclass TLoginServer : public TCRemoteDataModule
& U: c* | f$ x- \{
3 q3 l9 J/ s1 w- N...
private: // User declarations
bool FLogin;
6 R, o1 z2 u/ A& q$ rvoid __fastcall SetLogin(bool value);
bool __fastcall IsLogin(OleVariant &OwnerData);
...
__published:
__property bool Login = { read = FLogin, write = SetLogin };
};
在RDM实现类中
3 ]% E# B I4 i( S6 x& Gclass ATL_NO_VTABLE TLoginServerImpl: 。。。
* R' u0 ^( _$ s; u9 o1 Y{
% J2 }: N3 U) h8 C" G+ `// ILoginServer
9 C, m! ~" H/ a Yprotected:
STDMETHOD(Login());
STDMETHOD(Logout());
& b2 Q6 R. L2 o9 m; |) {( B};
然后简单实现之
__fastcall TLoginServer::TLoginServer(TComponent* Owner)
^7 B6 U$ { h. v* a: TCRemoteDataModule(Owner), FLogin(false)
{
}
- n2 T0 l9 E$ E//---------------------------------------------------------------------------
void __fastcall TLoginServer::SetLogin(bool value)
{
if(FLogin != value)
) [' i7 n' w3 z W0 t/ q* _{
# o. Q3 c; Z/ }( e7 X9 N: CFLogin = value;
9 U. s$ y8 [+ W" PdspAnimals->Exported = FLogin;
}
}
2 j3 D! N; q$ o0 m2 j% z! T//---------------------------------------------------------------------------
d6 f! ~/ G( i. |9 BSTDMETHODIMP TLoginServerImpl:
ogin()
{
* V/ }7 w( b8 X. \8 x. e4 A7 Q% Im_DataModule->Login = true;
3 N0 ?) F1 T/ L( R, s) C6 creturn S_OK;
}
//---------------------------------------------------------------------------
STDMETHODIMP TLoginServerImpl:
ogout()
{
- B0 l; H/ w- M# U2 u Bm_DataModule->Login = false;
return S_FALSE;
4 c! k7 S: \" q, I( w}
8 c: r ?1 J5 F8 ?1 A5 P//---------------------------------------------------------------------------
" c4 w% h! H3 L8 T6 Xbool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)
2 p/ G& i, n/ S1 E" B, E0 ?; [{
% ]+ x' }$ e5 o: Freturn FLogin;
4 z% }5 K; L) Q: T}
easy
这样除非你的客户端成功调用Login方法,否则他是无法使用
dspAnimals这个数据集Provider的,成功调用后手工打开的数据集使用完全相同
2 B5 |0 h" Z4 C! [0 U) P
比如客户端可以用如下代码
IDispatch *dispAppServer = (IDispatch*)(DM->Connection->AppServer);
ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;
* r0 }; I+ ? g* j& I; \dispLoginServer.Login();
DM->cdsAnimals->Open();
* L3 A6 J7 C4 P; a( z& G4 m: M9 ]/ ~实现注册,并且打开相应数据集……
% f5 K' H3 D j) A
因为大多数的三层程序对安全性要求并不高,因此这样的安全检测对
- k' @* r! x2 w+ V: c绝大多数程序应该足以……
| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |