QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2153|回复: 0
打印 上一主题 下一主题

socket连接多层程序安全性简述 - 连接

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2005-1-26 01:08 |只看该作者 |正序浏览
|招呼Ta 关注Ta

6 H6 L6 T0 a: y/ v$ G( u$ i

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

: w6 d" F/ n) W: Y+ V) h

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

+ N+ Y7 t7 E& N n+ U

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

% Q& [, G9 R7 i6 G) `: v* t

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

% L9 X2 N0 i6 o! n% M0 a2 C7 T

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

/ P0 T: U8 m9 S' y

+ x' c3 \% Q% f/ Z

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

, V/ u/ `! Q! O/ r

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

0 F$ s0 Q2 K/ \( I/ Z4 B

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

3 L% u! r- u& ?# @3 |; B

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

0 Y% M7 k! W( W; `

; W& H$ u; v* `" z% n

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

# _3 u* t2 p+ A4 e( U" C1 J

3 M2 ]8 z1 r% Z

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

" ~" o8 v+ J# A0 Y- G; D

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

5 _ D! r1 _6 d! Z! c7 K7 [

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

$ J$ F3 p' u5 J5 V/ }

interface ILoginServer: IAppServer

8 e, G5 S8 J1 t' B9 `' ]% s9 R9 Y

{

& {6 ^; i/ V8 R) H) `' N

[

, u& \" q K: V4 d0 |7 g, h3 e

id(0x00000001)

9 w) \/ {3 f+ U+ s [0 D

]

: y! A1 E: ?0 B5 D/ K( L9 M, U

HRESULT _stdcall Login( void );

e: G8 f3 y) q- T% ^

[

0 Y4 Y: {1 t! ]

id(0x00000002)

& m5 m/ m# G: \0 }1 u8 S

]

, Z0 d" A. w1 ?# d9 I, ?) O

HRESULT _stdcall Logout( void );

@6 U8 U3 H, E, t

};

$ D% C1 d4 Y5 i

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

( m! O, e, q( r! M; T( A

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

" Q0 G6 c2 G" q9 U8 b* _8 D

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

/ S% E+ A: C2 S. T, S3 V

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

0 {9 }! ? Y: |; L0 K4 r5 ^/ K0 i

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

4 x4 f; N$ ~+ l. l! }0 e) Q' r

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

9 x, A7 _/ G0 \+ W2 v5 ~# Z ^

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

; u' k% _# f) s- Y0 [

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

6 i8 @+ \ t8 O' A* V& F* ?

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

) ^ W: U: X% a! M- b/ u/ U

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

2 A; u+ F$ D" t& e9 U* Q8 h

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

3 \4 y) x, R) a* r; T

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

" k! S( P7 s, n4 ^

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

: m+ |; W' M+ @" d" O6 ^8 P

class TLoginServer : public TCRemoteDataModule

& W$ A! S: b+ m4 b5 U7 ]

{

% i; h+ D' p0 O2 _$ P

...

8 y% ~ `; @0 [) m B2 q

private: // User declarations

# @) f7 \/ L! b' X5 b

bool FLogin;

5 N) i. n' S: x( D

void __fastcall SetLogin(bool value);

. o- I! f$ l. A! q5 P( I

bool __fastcall IsLogin(OleVariant &OwnerData);

" z8 a/ r1 l1 j# a7 g8 H4 ~

...

o! U$ D! D% m( c

__published:

- e' I" m% U- E+ P

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

9 N% \0 a( q! j6 _* r& P+ x

};

6 e" S& e3 ]% g( ~/ u8 z

在RDM实现类中

6 [- r4 o1 M: U7 E# z. c" ?& \9 P

class ATL_NO_VTABLE TLoginServerImpl: 。。。

+ D+ T, l9 s& C1 P

{

- F6 `" u+ M4 v1 z

// ILoginServer

, D' J' i f) z

protected:

7 I* F# t6 J; V* M$ u

STDMETHOD(Login());

+ m5 |1 u5 C1 v5 t" Q/ i, U2 w2 o

STDMETHOD(Logout());

2 g: v* ~. ^+ T% S' k* T

};

2 b% b- ~! m) F# l

然后简单实现之

3 L6 N# H8 _1 u" q% S3 B# E# X

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

+ X5 d& l' e8 p( ?

: TCRemoteDataModule(Owner), FLogin(false)

) F( `9 N4 L: ?$ }

{

6 ?$ v4 n" f h! O

}

1 y& \% m/ n" Y8 a8 `4 [

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

& v; y, e: L; e9 v7 B7 o: {8 Q

void __fastcall TLoginServer::SetLogin(bool value)

W$ g# c& n7 x9 \% U1 D# C

{

" Z/ |4 z+ J2 m) r! H* r

if(FLogin != value)

% P2 Z. v; Y9 a

{

2 n B) @+ x* B, G# P* V" T& J

FLogin = value;

' R* l9 M6 R% }( o

dspAnimals->Exported = FLogin;

. ]9 h- N8 S& E/ z. a

}

& ^3 \, \$ z. W

}

* l( w3 z1 T* F7 @/ b V

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

, f V/ }) {1 Z8 n4 e* I, f6 z" g

STDMETHODIMP TLoginServerImpl:ogin()

+ {4 |' |/ E& w

{

/ y. `# H+ B; S7 M( m

m_DataModule->Login = true;

: \7 j# s3 C( c- W$ _0 H' { c( G1 \

return S_OK;

0 R8 A2 {' Q1 Y. E

}

! R6 I, v5 L; \3 z( y8 l

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

$ o0 ], b+ G" g. g3 J

STDMETHODIMP TLoginServerImpl:ogout()

. O9 Q& k7 r, `& |& m4 W6 V% ?

{

: w3 K/ f* ]- y5 p5 K: o5 W! n) H) c' K

m_DataModule->Login = false;

9 S3 K- q9 v* c4 l! O3 ~

return S_FALSE;

5 ]4 M0 I1 C9 n; S( B' J

}

c, N4 f+ J5 ], V

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

+ W$ W5 l( X$ v! A z

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

2 Y& s" R. U) k8 I& x1 P

{

& t8 @6 \8 [* O2 ~' m

return FLogin;

; p9 I$ I9 G0 Q# ]3 \% j; b) v6 n+ m

}

9 a/ V& Y5 [* r; S. C7 b J" g

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

5 L: B6 U3 }5 G" A

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

6 y. V$ v& I$ o8 ^ G/ Z/ `

4 @- J3 e, v: Q/ P

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

6 D- t# F. T+ I( ?

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

6 y }+ X' u5 r+ f) [9 V8 c

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

/ E+ g* J" a x

dispLoginServer.Login();

3 j4 ]: P# M/ M8 h' H/ A% R

DM->cdsAnimals->Open();

* j u. }' G1 } q

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

& g: }; C6 [/ J* E$ ?

" X. d9 R& b0 R0 v

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

5 D8 {1 U) {% D

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

zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-8-13 07:54 , Processed in 0.478724 second(s), 52 queries .

回顶部