数学建模社区-数学中国

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

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

" v% n% C# J* H; n, M" t: w

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

7 c3 Z, s& r# b; v' y4 J; A4 @5 v

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

2 S5 O. k0 m' v

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

2 k0 y Z4 e3 a$ v

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

8 `# D3 w7 X0 p V# t

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

# U0 ~7 h4 E7 E$ o; g

% R, Q; r8 A; S3 @: k# d r

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

# `0 K3 g* m" k1 w) F

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

6 p0 B5 b7 X F' G+ ^

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

1 a+ i( H. V# `+ y& @

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

3 K7 M$ l$ a0 \

- X1 |& U: o6 z2 x6 R4 f

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

1 l8 A6 \3 \3 d ?3 Q$ A! f

|9 U1 Z- g0 [9 r

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

7 h" D, g& P3 r6 R

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

# }, L7 l! c- ^& C5 P

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

+ n+ G4 a$ {4 |4 I( o9 t8 w. ~% \" K

interface ILoginServer: IAppServer

2 A i( e6 e" k8 r+ |' V T% q

{

% f7 p" h1 Y0 x

[

, L9 S" c- g) ~0 a

id(0x00000001)

7 X& J! I! n0 w1 J

]

2 r+ ~$ ~& N4 c$ n! I

HRESULT _stdcall Login( void );

8 s3 c- `9 i6 ~9 E; R, R3 ]

[

9 p) @! ^) J2 v Q! V7 r

id(0x00000002)

w7 }, u6 f2 [' m2 M- x: \: W" W! N+ {

]

0 P8 `- ?' W+ w

HRESULT _stdcall Logout( void );

' C0 |7 \! m: r1 Y5 ^7 c- V1 _* Z

};

3 w0 W; l% I4 G9 n+ r, a! e

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

! k) y L" l! H

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

+ H, k$ o& c( M4 H* v# f7 B' l+ }9 t

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

' {) e8 G9 s3 |

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

+ w: Q, I( `) [! } r

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

6 F- U6 z1 R8 w3 w

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

) k& ?; q& D& m7 N# n8 x- `0 t( V

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

* j* Z' k3 |, Z9 i0 _. s, G

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

, m( y3 o" d0 H% l0 ^ B

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

& C, ~, D3 E4 d

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

: U$ H! ~. S3 S* ?2 Q* A# W( J

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

! r1 `' `3 v" E( [8 _( H2 s# D

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

* o; a; Y: W, o) P2 ]! \

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

/ N: Z$ C6 {3 ^+ A/ n+ |4 R

class TLoginServer : public TCRemoteDataModule

/ o/ ~8 J6 E2 _( P

{

! m, V* P7 d4 H# w8 K2 B: d1 W6 c% N

...

2 ?0 u- _0 g% h) J0 a' l% `

private: // User declarations

: |7 M3 ^* g) T+ e6 c) s7 q

bool FLogin;

' W" w9 _( V" g

void __fastcall SetLogin(bool value);

) T, t6 W: ^- S. H& d4 h: ^! a* T

bool __fastcall IsLogin(OleVariant &OwnerData);

! G& m5 s! u9 h% ]5 N% ^

...

/ ~: q9 {% N% y' s4 w$ m

__published:

1 C) a7 _) L2 l8 r2 F

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

! K3 d$ j* B: |6 g, Y# J& Y* N" l* w

};

/ A% A) @+ g* m/ ?1 K& x5 b

在RDM实现类中

! A9 i1 ~1 H- n, X: x: v/ f

class ATL_NO_VTABLE TLoginServerImpl: 。。。

]6 ]5 ]6 U5 I% Q. I( m# `6 ~! D

{

3 S, I7 [* y1 A2 f

// ILoginServer

/ m* j" v* k B8 X& ~

protected:

% X( x1 N2 d9 O* j6 T2 q

STDMETHOD(Login());

& c7 m+ R' y7 \' E T

STDMETHOD(Logout());

) L5 G4 }, c4 [) c

};

$ g* U, Y; x" _- m& ~

然后简单实现之

! L5 ~/ p' w( G% j0 V% _

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

+ G* I% f, `. T! M p8 |3 h

: TCRemoteDataModule(Owner), FLogin(false)

" t! [7 L5 r+ Z u' ^( F* J

{

# k9 [) r: n8 o8 T$ A

}

. l& {( p* F2 t' y0 u, V, C

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

- k U2 A: }( ~7 w

void __fastcall TLoginServer::SetLogin(bool value)

2 p6 x% O" Q! D8 j; u! V9 M/ b! w

{

# Z b" e+ G; o3 ~, y/ V

if(FLogin != value)

- w3 }' B z* b7 B

{

% u+ n, _" X" C$ b% I$ ~0 S

FLogin = value;

) c9 W6 C+ q* Y1 p/ B2 N0 E

dspAnimals->Exported = FLogin;

! B: T8 x4 F8 a; r

}

; M0 P( E- b7 m% X& F

}

, _& J8 p* E V/ @& _

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

( [. T) V3 |. I' ]

STDMETHODIMP TLoginServerImpl:ogin()

2 N/ C+ R' F& E1 b: O. u+ t

{

% e" p$ \5 j. z( j

m_DataModule->Login = true;

+ h7 R8 s) u5 }: A: R7 c6 F* k$ H

return S_OK;

8 D$ ^8 T4 R& l* u0 ^

}

7 {/ {" f& r$ C% [: T" b* {( F) |

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

1 F& S* _. i% w5 d% r0 a

STDMETHODIMP TLoginServerImpl:ogout()

: e5 {( k- `& ~/ j; ]( |

{

7 K2 X7 M- E+ Q

m_DataModule->Login = false;

0 y' h E$ a/ s9 p

return S_FALSE;

4 k" i7 a- y7 O. g K

}

- }8 d! S: `+ \( h% O$ j1 s; j

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

9 d: e0 e& I; k

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

7 {8 ~4 ]; |0 w/ l7 ~" ~7 Z8 K

{

) _" a7 ~! \# n3 f' {) n

return FLogin;

: {# |! Z$ I0 Q4 K- [

}

2 _. N. ^5 y# v' m% p1 R

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

: m f4 A8 e$ v8 F

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

4 K) ^0 ]/ J* I+ x$ Q7 p) B

; d' m" U1 B6 V7 e

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

- B1 r1 P1 B; }4 Z" \

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

- Z3 p" l$ |& ^+ n

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

& i) I! l( ]8 r: }2 \2 v

dispLoginServer.Login();

' M+ Y; c1 m; g# e

DM->cdsAnimals->Open();

3 @& _) Q4 _% g! j% I0 V

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

. A; ~$ K5 W( }. X8 }

+ j/ L- y4 t# [

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

! I- y( Y% @! q3 ?) G

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






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