数学建模社区-数学中国

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

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

: b+ T; N7 A7 w2 w5 y4 K2 B$ B

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

, i C: d6 v# B' r4 ]

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

5 G& b& p) q1 g& J3 c

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

6 |8 H) @) J1 s" s% `2 N" A

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

; ~- {: f" p! m, n

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

1 [! B( q: @" E' V3 N; A

6 o: @" Q* {2 m, |

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

1 i0 R9 s9 E4 M. m8 B+ U

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

z; Z& h Q* h- R0 F. v) h- }

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

/ L+ _, Q4 P3 ~: ^- D* P

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

6 W3 L7 V! q( E2 U8 U

T3 e/ C6 ?. o* J, s9 [

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

& i. k' ?# J9 h( R

\! d; X5 }' M$ S0 g

因为tcp/ip是稳固的连接,因此每个连接,也就是每个RemoteDataModule

/ \7 m! Z3 f |- t

实例检测一次即可,实现方法很多,这里简要介绍一种最简单的

$ U' G9 I7 N7 t8 n8 J4 K8 h

可以在服务器端的TypeLibrary里面为你的服务器接口增加若干个方法,如

% D' C' m3 h& t% C( p0 q; w

interface ILoginServer: IAppServer

: m, }6 I9 U; R% Z

{

0 h0 t* q- t: L( J

[

% t1 C P0 H% x

id(0x00000001)

]4 s0 ^+ ?/ t4 Q- d

]

7 Q( D- Q9 N: W

HRESULT _stdcall Login( void );

/ x& j/ s) G0 h* Q) {2 L

[

& J1 y2 H: `% H' [6 A1 C4 X9 {

id(0x00000002)

2 `( {3 H9 N& K, S# }

]

. ] u# D7 X- ^% ]2 Z# v

HRESULT _stdcall Logout( void );

4 v2 \4 a& q( M9 F

};

- J! i# Z4 p* [) N/ Z8 o& o

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

5 G* ?- \. f; \9 W& b- [

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

/ Z7 F5 [9 t2 x8 @

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

2 \0 R$ w4 p, J3 n% j

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

) _$ Y- e8 p" @! n0 M: G& M

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

. W X4 Z& ]0 i7 J6 m6 G

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

* x' E$ ~; t/ A" T" a; P

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

8 @6 g7 U+ c5 ^4 K2 \' Q! T$ e; m

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

! }" e( i W. l8 R( Z$ k

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

: _9 ^6 {: c' v; H1 m8 r

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

, ^" f% A, F1 Q2 k1 p# T1 Y' I6 t4 U

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

* \8 S+ B3 r* X% v7 h

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

5 k$ Z9 a' a$ H& k* L' O' k; K

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

1 b& W6 w+ F% Z% y

class TLoginServer : public TCRemoteDataModule

l. D4 C2 ]5 }( V1 I% q

{

% ?: C* G1 C( e7 G

...

% k- o: A5 U6 d" c% y7 V5 j

private: // User declarations

: n( |8 Q! g; I) ]* @1 x

bool FLogin;

: e+ s0 Y4 K3 s, h1 V

void __fastcall SetLogin(bool value);

, K' I0 w5 p0 P# Z; v' @/ [" }

bool __fastcall IsLogin(OleVariant &OwnerData);

3 M$ M! I; Z9 p. Q3 K9 I1 p4 Z

...

3 a1 j7 d5 y( Q8 N, k

__published:

8 w; j' K9 h" s, n/ ?! p; n8 P

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

. J( S2 }4 y- ~8 g

};

% L/ }" Y# f1 y2 a0 T# u) h

在RDM实现类中

. o9 l: a" |( R& |3 ]6 m ]( g. a

class ATL_NO_VTABLE TLoginServerImpl: 。。。

; q% H! E) q* U

{

- `! U5 {3 C+ m+ o1 g

// ILoginServer

! S- A* Z' C$ c1 W3 P

protected:

) Q! @6 P, n8 P0 ]- n, D4 B- G

STDMETHOD(Login());

% |5 t5 U) P# ^1 P

STDMETHOD(Logout());

- V# I5 S2 g5 B

};

+ U3 i2 i2 d% m

然后简单实现之

7 e' t2 D8 C9 C+ D

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

9 @% |$ ^3 N1 }" g4 p

: TCRemoteDataModule(Owner), FLogin(false)

2 S7 D7 e% ^! ^0 ]( d, G

{

: P3 ?- l# g$ [( m% g c7 N

}

6 B/ Z0 ?4 a; S6 ~

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

, K$ v- e' ~9 T: x0 _! u( L; ?+ X

void __fastcall TLoginServer::SetLogin(bool value)

7 k. u" B& V* f; z C) Z$ }' w

{

. z) g, T2 J6 ~0 K" z

if(FLogin != value)

4 ~3 k7 [ R6 c% W: V8 s5 I5 X

{

' p1 {! H6 Z' X; ^) u7 Z9 y

FLogin = value;

( \, O6 v6 Z2 j! {" m9 C2 Z

dspAnimals->Exported = FLogin;

: |7 f& Y9 f8 ~6 G' J% I( G

}

7 D7 Z# @. ~ y+ c( k$ x) [

}

: q+ G( x& ?1 H3 s* b

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

# ^' c' y' {3 p6 l( e/ K

STDMETHODIMP TLoginServerImpl:ogin()

8 }+ F4 a" S! G

{

+ v# L# Y4 c+ Z

m_DataModule->Login = true;

# E2 B$ p' n; e# Y

return S_OK;

0 h" k/ q0 ~# \" m6 S" {

}

# o X$ w* k5 }4 q7 Y

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

+ K% L( s0 k: J2 E8 X9 |9 i7 e# G

STDMETHODIMP TLoginServerImpl:ogout()

+ t8 ^0 l( u% o

{

) D, @) a6 h. N+ f1 r- c/ y, d

m_DataModule->Login = false;

- w9 g: j! w4 p9 K+ a! |

return S_FALSE;

. @+ `: G* s) v4 n3 f$ v9 C

}

; k5 \# C& M9 \, O

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

7 D0 A+ ?0 S' V% x/ C1 @ `

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

' v( S- D* g0 D( D2 y& P/ E

{

$ a* r4 U* J$ T; i" U! N5 u

return FLogin;

0 s9 O4 k3 o I" m. `5 o+ p3 _: f

}

& l) f* ?0 o; [) b0 }1 T1 x

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

; e% S0 E6 W. w4 T: K2 N% L

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

( B* O& c( H- Z0 P$ P

9 c8 P1 R8 c8 f% Z% @, y, x: z

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

$ @# Q, A" l1 U n' x

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

- |+ Y1 q$ E! ]( s8 r* o/ c

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

# e f/ y9 i/ h6 z# t8 `

dispLoginServer.Login();

! z3 c) `( C' C0 a. i

DM->cdsAnimals->Open();

, C6 S) Y5 M I! P. Z

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

$ C9 X2 _( c: F/ u

4 M1 S$ T. P- n- j8 Y. V; _6 Y. _

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

- C t# g7 F; F

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






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