数学建模社区-数学中国

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

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

/ t* O0 L1 d- c0 F) L+ Y1 ?

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

! x7 z3 V& p/ X/ _/ B

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

) Z, k5 i- ~, d

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

" E! B% u' D* F9 k& t

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

) P7 w+ U6 D! c

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

- M8 J6 B: N! M/ e

+ J7 {# ~- G" Z, j: f) v# V

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

$ _! C/ Y( @8 M) s& }: i

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

/ L7 {9 \4 U. q

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

' U, K2 s" e' B V

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

& m" e- q* ~& d4 U, w- `

4 T# A7 s; m. _; t$ J

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

, \& t% f( f) R. M: r+ k) S8 S

' T8 Q) y; z) O5 h D. P; {( @

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

/ w4 m5 r1 c8 u% R& S4 J+ }; G

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

^1 H- T% y* i L0 p/ e4 w

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

0 y% J7 m+ {& o7 G7 v! B5 u! \

interface ILoginServer: IAppServer

+ m- Z' |# \& c6 S

{

* N( q3 F( \' V+ p6 F

[

: c* h7 y) X( U( |, X# i5 |

id(0x00000001)

- L7 v: J) G) J3 u

]

+ A2 n: e0 ]- C. S+ y P

HRESULT _stdcall Login( void );

7 ^! f! u) ]$ c' w/ ?5 D6 U/ I) `' s

[

2 M% U% Y2 F6 h1 e

id(0x00000002)

+ t' `9 X/ D8 Q+ g, E

]

0 _2 d q) Z1 L% Z

HRESULT _stdcall Logout( void );

2 u$ b% T& {" O( F1 K

};

" g9 s: n8 a4 X* j! J

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

# M1 B' ^8 ]+ V3 `- o

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

1 k7 S i6 `* U W" e- e; d

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

: e9 y0 Q% N- I

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

9 E% d$ B; ]; a# n4 V

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

) G! t. w( J: h6 ]- Y( y

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

! I5 W h, R) x0 G% k2 c+ I4 E2 W

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

0 i7 I& S3 t3 {

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

S) F3 N* @, E+ ?) E. b

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

5 M+ S5 t W9 X$ c

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

4 S( e) j% {4 m

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

4 O$ l: ?( d+ ~& y2 o

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

2 c; m) K/ C; b- x* d( `. T

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

# L6 j7 C" Q$ \5 M, L6 y/ `) Y2 ]7 A

class TLoginServer : public TCRemoteDataModule

& U: c* | f$ x- \

{

3 q3 l9 J/ s1 w- N

...

% Y v" G4 s$ }0 k1 L: H" z- b

private: // User declarations

* Q1 ~ e! \0 z) O$ C

bool FLogin;

6 R, o1 z2 u/ A& q$ r

void __fastcall SetLogin(bool value);

0 X2 R. ~. R2 i; N0 L3 E6 U

bool __fastcall IsLogin(OleVariant &OwnerData);

, K4 j( \2 t, p+ U& e

...

: D! ~+ a* U5 p' \7 k6 @7 N

__published:

4 o9 O9 {6 ]6 }; q3 x# ^

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

' V6 v+ w5 [3 s8 U: i8 }) ~

};

4 M$ O& y" o0 {) t: w6 a

在RDM实现类中

3 ]% E# B I4 i( S6 x& G

class ATL_NO_VTABLE TLoginServerImpl: 。。。

* R' u0 ^( _$ s; u9 o1 Y

{

% J2 }: N3 U) h8 C" G+ `

// ILoginServer

9 C, m! ~" H/ a Y

protected:

% f; {; f' J/ J. O

STDMETHOD(Login());

- A) ^* g0 E$ Y# w1 z6 g O

STDMETHOD(Logout());

& b2 Q6 R. L2 o9 m; |) {( B

};

$ I0 \5 d- X+ V$ p

然后简单实现之

" p' r3 C6 U+ U

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

^7 B6 U$ { h. v* a

: TCRemoteDataModule(Owner), FLogin(false)

2 y3 m% S% O) w8 W% M8 V

{

1 Z" N& a: d) B4 ?) w% d0 ~, [7 J

}

- n2 T0 l9 E$ E

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

/ z4 b5 X) K4 L( N" \: ^- p r0 K

void __fastcall TLoginServer::SetLogin(bool value)

f9 ]) A6 n* {$ Z3 [( h+ V0 ]

{

: m$ }3 m! O; t+ u& L& M* M

if(FLogin != value)

) [' i7 n' w3 z W0 t/ q* _

{

# o. Q3 c; Z/ }( e7 X9 N: C

FLogin = value;

9 U. s$ y8 [+ W" P

dspAnimals->Exported = FLogin;

$ e, y6 s" T0 |

}

* [$ {" U" J4 E5 ~) o9 _" V

}

2 j3 D! N; q$ o0 m2 j% z! T

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

d6 f! ~/ G( i. |9 B

STDMETHODIMP TLoginServerImpl:ogin()

7 r, l7 } K6 J& A: s$ z* p7 e

{

* V/ }7 w( b8 X. \8 x. e4 A7 Q% I

m_DataModule->Login = true;

3 N0 ?) F1 T/ L( R, s) C6 c

return S_OK;

/ v* J/ h# p u. n2 W0 {' d! |

}

7 l0 w8 D: ]0 b1 \% z# W

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

8 K, H/ M4 d6 f. b7 \

STDMETHODIMP TLoginServerImpl:ogout()

+ k' B/ m; R: @% M. j

{

- B0 l; H/ w- M# U2 u B

m_DataModule->Login = false;

6 ~4 ^3 f% k" J2 E

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 X

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

2 p/ G& i, n/ S1 E" B, E0 ?; [

{

% ]+ x' }$ e5 o: F

return FLogin;

4 z% }5 K; L) Q: T

}

# v* c6 k& q9 C, m

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

4 S7 |6 I8 @ i# B# s

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

2 B5 |0 h" Z4 C! [0 U) P

! c3 E& }/ A P1 M+ ]& b# t

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

( n* ^: f7 P8 J1 [3 A

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

u) `, \0 S) ]. h5 U. v6 i/ Z5 x

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

* r0 }; I+ ? g* j& I; \

dispLoginServer.Login();

6 L5 L* y' Z* o1 Z* L9 k1 d

DM->cdsAnimals->Open();

* L3 A6 J7 C4 P; a( z& G4 m: M9 ]/ ~

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

% f5 K' H3 D j) A

% N# w; a8 b6 N4 T

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

- k' @* r! x2 w+ V: c

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






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