数学建模社区-数学中国

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

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

6 a5 p. N' i$ i+ z. D

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

: z8 w3 s/ z3 a

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

! d4 z, P: b. K0 t+ ]) F( |! u

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

( o. x# _0 A* O3 o# P

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

% g) h, g; x( K

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

& e$ U: o6 Q5 M

6 z; y. _3 l( B( s" I

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

, F- N( d/ d! e m

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

+ R" Z4 z" m& ]2 G

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

- Z- b& ~. V% v+ ^' c' I

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

( I1 {% g& b" z& d7 r

( N, j, R' P0 V8 u$ O- L

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

$ i: }; b5 j1 C. x, C% o+ R

& j; }, k# a. b2 T

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

0 _- ^* W! K$ d, O, {

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

/ ?1 i' J5 L: `& k

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

1 K C) d4 h& Q

interface ILoginServer: IAppServer

$ n" @) c7 T" l

{

0 s( ` t9 S% [

[

5 w# W: ?! e7 @) M& Q* U

id(0x00000001)

. G: L9 z Z: x# {' x: Y

]

& [' F8 B0 e- M

HRESULT _stdcall Login( void );

9 L$ P* y* e0 J5 v [: q2 Q

[

% q r* [8 i) i, G& Q: \" `

id(0x00000002)

# V6 @. s' p$ B' X; ~4 n

]

7 X& Z( k, m1 h8 x- P

HRESULT _stdcall Logout( void );

/ T6 ?2 }0 [, q- i$ q ^$ b

};

7 r8 g* S( l( L' H+ P

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

, e6 ]! D f4 Q

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

$ u9 L9 F8 E! K1 v. ^) u. d

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

8 x/ o7 Y$ i+ t* u

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

9 t) _, C8 a9 M9 G0 \. `

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

" c' h: |2 x0 w! i

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

$ n* a% Z; e' t b7 }" i9 ~! ^

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

- z) _4 g; |: u/ f1 s

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

# J* d( _$ `% L

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

6 o7 V" B( [ \. T! J

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

+ L( r. a* z+ b$ I$ R0 b# v1 Q7 w

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

4 w, S0 {. J% M7 c4 R2 q+ X3 t5 L

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

% c! v4 E E, U

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

1 g5 a$ ~+ s6 i2 b& J

class TLoginServer : public TCRemoteDataModule

0 F0 q( \7 i7 @5 p A$ ?$ t, l

{

2 `: b$ s, J1 v( N+ ~0 f/ Z

...

4 k$ @0 L1 x% Y% b) z

private: // User declarations

6 N) p7 e1 \2 ^# E3 [" Y) n

bool FLogin;

- i) h5 F+ A8 a3 S! ~5 v

void __fastcall SetLogin(bool value);

: A# Y! k, _' t0 m2 p$ v- h

bool __fastcall IsLogin(OleVariant &OwnerData);

& l1 e' X/ ^2 {" C- J

...

( V# m* h! d6 C! Z7 ?, U

__published:

4 z) T) B( |4 P3 p. \# C1 z g: E

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

7 N6 W) j u. j! A/ q6 x# o4 }

};

9 ?6 F1 j8 c% c4 }, m/ W

在RDM实现类中

% s& L+ | ~$ X7 i6 _

class ATL_NO_VTABLE TLoginServerImpl: 。。。

/ P4 j8 h7 t5 H1 F% B' \

{

" @5 n7 W- R, i; C N( C& T

// ILoginServer

W# M2 r2 U( B! H2 h

protected:

3 M6 r% N: V7 B. o# ^

STDMETHOD(Login());

7 Z* N* E3 N; O$ P5 M

STDMETHOD(Logout());

- _- b7 }" Z, D0 f7 c: B* Q

};

: h! C% M3 K5 W! D* U

然后简单实现之

6 U. V* d% U) Z+ P

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

/ \! q0 g) [9 S: B) m

: TCRemoteDataModule(Owner), FLogin(false)

( x$ K" D) J0 \& i7 B8 E% ~

{

* J0 W; } K; j( V$ m' I; n& m

}

9 a% O; t8 |: H

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

1 o% ^4 v2 l' K$ k

void __fastcall TLoginServer::SetLogin(bool value)

8 g, \3 [" x5 u$ y& l6 A

{

# N- G7 n3 w2 ~8 K# {, w Y" I

if(FLogin != value)

; ^6 ^2 ]) s" w, |

{

3 s: Y/ f5 M& P4 h& t' ?2 q

FLogin = value;

& c/ t( Q; f3 X* f

dspAnimals->Exported = FLogin;

% A: l' n. Z; A8 w4 L

}

, B7 o" ^1 V% R! z3 u

}

: V- n3 j& i$ h( }( B

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

& \* D( F8 l/ }& Z5 O1 S

STDMETHODIMP TLoginServerImpl:ogin()

& w/ z7 ?, u% m& {( {1 u7 N- X2 A

{

7 @- ?) M- M% ?

m_DataModule->Login = true;

7 j7 J3 f& j* t, f

return S_OK;

: ~& i! ]* D8 Z6 p; M- S: q; V+ E/ X: E

}

1 u) ~( a: h: a, y+ R

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

- {- o) Y# Q3 X& e4 s

STDMETHODIMP TLoginServerImpl:ogout()

! A P' W) \4 }1 Y7 M9 T7 ]( S' {( H

{

2 u, C1 s, _ r0 S: o5 y. s

m_DataModule->Login = false;

. S8 m& n4 ]' q8 J1 p3 J

return S_FALSE;

; l$ q+ r" ^ O; W( ]# Y

}

# A, X2 n; y% j: B: F: x. T! [" ?

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

. \7 \8 @& e7 v/ |# B

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

) X# X) f: u* p0 m0 P

{

7 {( l4 @( O# Q* r% v+ |: d

return FLogin;

N9 I! G8 L2 | _2 r

}

5 n: Z( e5 O4 G2 r* ?! m. y7 b6 O8 y

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

- c6 A, Z6 B/ Y

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

! T" H3 {1 U: n

. F; D7 y4 e' A. s6 H% o' Q+ d: l: a& _

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

9 V5 Q F% s+ k! E

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

9 A, r E2 x2 D' H/ i3 K

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

* ~, y0 s8 x8 X' X) y8 q

dispLoginServer.Login();

& }6 u* Q6 C- W) U0 c

DM->cdsAnimals->Open();

5 w0 O# \* F# J" ~; R# J& Q

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

1 p6 N: P: Y4 }7 G

3 Z) C& a: C7 J: I4 N' ^( d/ [

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

0 j$ ]5 E0 L2 h1 i* q+ j& p4 Z

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






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