数学建模社区-数学中国

标题: socket连接多层程序安全性简述 - 连接 [打印本页]

作者: 韩冰    时间: 2005-1-26 01:08
标题: socket连接多层程序安全性简述 - 连接

- m, G5 P; K4 w

前面hawkfly提到的在多层编程中,服务器端安全性验证的问题

7 R. P4 R* M2 M. {# k: v6 c1 e

在以socket方式实现MIDAS时尤为明显,DCOM/CORBA都有现成的

! ?" I K' o- S* f4 V

安全管理功能,而socket方式在这方面比较薄弱,没有现成的解决方案

4 n8 e6 k& `/ [: t

现就我以前对MIDAS编程的理解,做一个简要的介绍,

" {" B8 F, V9 p: Y& R5 y$ V/ B/ q

以后有时间精力再详细举例说明

7 [- w/ b/ i! x( ^) a+ v

4 ~% y7 [- k' a4 o7 _. }( Q0 T

win2k中dcom的安全级别有7种,其中

$ @1 c* J5 w N. c/ b u) j" V

最低的“无”安全检查暂且不论

; ^" _ S: A9 O

默认的“身份验证”服务方式几句话也说不清,

6 M: l8 H: q! y& `6 q( Q

先放到一边,看看剩下的5种

* S& }* ]1 V" H- H

( M7 E) H6 _; l& R3 o5 Y/ w

1.连接,仅对初始连接进行安全检查

, g) r% J9 ~# E2 _: Q* i! D

+ L! ~4 y" f& C3 i

因为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- {* s

interface ILoginServer: IAppServer

2 a) j0 T2 N6 `* A/ g

{

* _0 C$ C5 A/ c4 {! k' M8 a+ p

[

4 x6 {& G- J3 w! y. K7 x! _

id(0x00000001)

- e/ Q& ?& F$ ?

]

0 `; w8 R1 J, p! n

HRESULT _stdcall Login( void );

$ e! H o% X/ F# l& k8 K V. J

[

0 o; e) ^2 {+ o

id(0x00000002)

" R' Q2 B1 v5 i% _) z1 ?# m

]

8 {+ S3 V1 l- c% W7 C+ Z3 _

HRESULT _stdcall Logout( void );

0 F- S5 n! ` U! h" C" k) ^' X

};

& S* H6 p0 P4 {5 i. |

在方法中实现你的客户身份校验,而在校验之前,通过把RDM上所有的TDataSetProvider

3 c4 }& \0 N0 d" D1 Z! H7 H! @1 j

的Exported属性关掉即可让客户端无法看到服务器端的provider

+ i' f& a/ O/ A5 Y

因为客户端实际上是在连接服务器成功后通过服务器之IAppServer接口访问

# f% j7 X$ B! c2 F' w; R

所有的Provider,如IAppServer::AS_GetProviderNames可以取得

8 N5 I6 p3 |9 W. M" k: n' \) C

服务器端所有exported的IProvider接口名称,而所有数据的取得、修改

9 g* ?3 H3 o7 o& |; E1 U* z

都是通过相应的ProviderName来指定的,如

4 m9 [* Z! D8 n. m, U9 J

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

+ b9 R) G; M* L

t Count, int &RecsOut, int Options, const WideString: CommandText, OleVarian

; H( o8 l2 | y4 i

t &arams, OleVariant: &OwnerData, OleVariant &GetRecords_result) = 0 ;

5 D& t2 J: Z5 g

取得数据方法的第一个参数就是你需要操作的数据集名称……

/ h3 n' E7 i, J

如果你把服务器RDM上所有的TDataSetProvider::Exported关掉,

# T( a/ }; t( ]4 v7 h

则客户端看不到任何Provider,也无法通过其ProviderName取得数据

) q% O0 [" g3 ^% g

例如我在服务器端的RDM类中加入

. C' b4 L! M; i; D- }: l8 N

class TLoginServer : public TCRemoteDataModule

Y9 G0 ^8 R1 H# b* W

{

4 A7 T3 F% {- h' R

...

0 q) G- f( h8 O3 y3 @% u4 r5 c

private: // User declarations

& k) U) V# W* ?, X1 W! ~# G& @

bool FLogin;

1 s7 J; E* D. z$ z& m

void __fastcall SetLogin(bool value);

7 o- D$ H( C n" J- W8 |1 `+ P

bool __fastcall IsLogin(OleVariant &OwnerData);

: T$ V" A, f& c

...

" r; H4 _5 O! L, F& {5 R

__published:

" t% T2 U* m* _, f- \: l2 H8 J. ~ |

__property bool Login = { read = FLogin, write = SetLogin };

- u5 b7 \2 z% A5 N

};

- n F( u1 C/ ]: p! q

在RDM实现类中

+ e: W9 y6 _( A9 W

class ATL_NO_VTABLE TLoginServerImpl: 。。。

) Z1 ]. m4 ` W# z# ?5 s4 c# _

{

( j6 Q0 f0 s) [) v& M1 m" n

// ILoginServer

0 v/ e- P4 u/ [/ Y$ N$ J

protected:

4 x5 c, Y1 _9 T- N$ D' a+ j( m0 Y

STDMETHOD(Login());

3 O9 `3 D$ V( u/ L5 J

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)

$ j( [, w; ], P! G) S/ q: T, E

{

# J! }) M" ]3 N/ c1 ]

}

: T! d$ M. b; p

//---------------------------------------------------------------------------

; |* G( f- r' [7 J/ Q5 J

void __fastcall TLoginServer::SetLogin(bool value)

0 U# \7 \# @/ F! O$ e5 c

{

: W0 y4 m# a, X1 Q! T( M

if(FLogin != value)

2 z- Q) j5 w) Q2 r4 G) ]& T

{

/ s6 ?9 C* \# {3 e

FLogin = value;

) }5 `2 O* x$ V! d% H

dspAnimals->Exported = FLogin;

* l* G/ H% O/ ?- i% G! h! Z& k. H

}

; O, G1 ~/ U, h8 ?; k- ^- M) k

}

$ O5 {. \- m# R2 q9 V2 I

//---------------------------------------------------------------------------

# P" ^1 {5 O9 f1 [. h- A

STDMETHODIMP TLoginServerImpl:ogin()

7 x- M! b2 w: }* k! X

{

* [( }. r. u( T; I6 h

m_DataModule->Login = true;

7 W" c* u! s) \2 y

return S_OK;

4 `# r8 X6 g; E9 T- N

}

/ V- K: J K5 a/ @2 W' T

//---------------------------------------------------------------------------

# D) @% n# v5 E, I( g

STDMETHODIMP TLoginServerImpl:ogout()

* ~' ~5 k" d: L' y, e

{

7 _# r! p+ S5 w* ~/ }" U

m_DataModule->Login = false;

, R+ i$ A. A7 Z, r, I9 Y2 p, w! E8 S

return S_FALSE;

& a9 ~: x+ Y$ t' f: r4 K1 c

}

" h( `% G( Y0 |0 o. }$ j

//---------------------------------------------------------------------------

3 ~! `; f" q2 o: o( Z# A

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

6 h& y% i7 T* E; I

{

& h3 C6 I6 g+ M; w: X4 X

return FLogin;

9 _( c! T1 H! ]! w/ O' a

}

. q+ p* |6 D; b' L2 R

easy 这样除非你的客户端成功调用Login方法,否则他是无法使用

, N7 D& q6 f) r" v

dspAnimals这个数据集Provider的,成功调用后手工打开的数据集使用完全相同

/ Y, J* n( d3 h! k" O- ~

' u G/ h1 U9 \0 Z9 r1 H! P

比如客户端可以用如下代码

( m f# b. g9 d

IDispatch *dispAppServer = (IDispatch*)(DM->Connection->AppServer);

: W% \) D; e# R: L) B9 G- |

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

6 @" m1 N3 i- u: ?

dispLoginServer.Login();

+ `2 P4 j1 N V$ b! h; p

DM->cdsAnimals->Open();

; ]3 K8 @( S" |$ Y" l" w$ A0 m

实现注册,并且打开相应数据集……

5 A9 L& \7 y# Y/ H

) O# u, D0 G' W& k7 O8 S

因为大多数的三层程序对安全性要求并不高,因此这样的安全检测对

) @- e5 b: _8 W& b4 E B ^

绝大多数程序应该足以……






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5