QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

) k1 `; C+ n0 _: m# A

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

- [7 D: u% X' k/ N9 v; ?

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

. L! A1 s- S8 s2 d

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

) s) e" A8 k. B

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

" I' E* @$ v, y6 E$ L# Y5 ^

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

1 k6 U8 s: O% I$ g

6 U: K. F$ W# G8 D

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

& p2 H7 _; Z/ P# ^% m Y2 l: Y8 c

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

9 D$ }2 H# D) ~5 t( j

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

8 _" S( ~! E% k

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

) {+ q: C, S E5 b5 C+ u9 p

3 A& @, Q3 A5 [+ A6 ?5 P

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

7 q& j. `( O5 ^4 I& x5 X

& j6 a$ `$ t. o* X" f0 p4 ~" U

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

4 e& O# \3 S) A0 D

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

* s( v. Y! e% ~! b! A

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

6 u; P0 ]2 M9 _( I9 s7 A o3 Q

interface ILoginServer: IAppServer

- ^; N3 b* ?) ~! e8 w5 y' l

{

4 d8 Q* {/ o1 E7 D" w8 c4 C4 V

[

3 J2 C! o! c: c; g; r: U, }3 G$ g

id(0x00000001)

& s8 q# `2 E* {5 P5 G: R3 n

]

$ G! G- H4 ~5 g# r3 B3 a/ w

HRESULT _stdcall Login( void );

( V, K( s- c4 [2 {

[

2 y2 h- P8 t( r. ]: _8 x9 M

id(0x00000002)

E2 S1 j9 D! b$ N; N, \7 E

]

( v/ b2 o! u) p# Z# y9 \

HRESULT _stdcall Logout( void );

& Z- L+ ?2 \ \6 n2 \0 W

};

& W& }; V) [- L$ u

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

: u, G9 @* O3 G$ f

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

" E" r* c" ]! w' f( r) ?

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

! O# c! G2 V k$ L) n

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

. [( c4 J( {2 { e) y' {1 N1 C" y

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

4 U; V) V [+ W

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

2 h9 P+ R: r+ ]5 z0 g; A5 \5 b

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

7 g) i1 D3 t" c0 L

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

s1 H' z, m2 }8 n* b. s& G! F

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

9 `7 i4 \ }0 E( j

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

5 m0 A' Y: q* Y0 W2 Q- B! {

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

6 d3 F! h+ |7 w

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

$ Y; n" E$ L1 P- l% c

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

% I/ s1 b* j- p5 p' K6 G

class TLoginServer : public TCRemoteDataModule

[0 }/ x. b2 p* }

{

5 ?# o; E3 l8 B% P* o

...

! B6 b8 {+ ]6 Y( \7 c, |# {

private: // User declarations

& l; A# n4 ~6 c4 r

bool FLogin;

# m4 ` a. b7 t2 i- t

void __fastcall SetLogin(bool value);

: w7 X1 R4 A( O) A& \

bool __fastcall IsLogin(OleVariant &OwnerData);

0 I; b% W: D4 z; x7 s

...

; T. S3 ~, ~, O8 g9 i/ b

__published:

; K, Z6 X/ r# e; G9 i8 P5 ^" S

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

9 S) g4 N* y0 g3 r0 |+ B8 ?2 v/ f2 g. n; f

};

- W; {( W* I5 h8 o" B

在RDM实现类中

8 g; r& U# j# ~, p/ g3 o5 M

class ATL_NO_VTABLE TLoginServerImpl: 。。。

0 w$ @' i% ` w% w

{

; P) f" ]5 J/ [

// ILoginServer

1 i/ I8 P2 C8 @

protected:

/ i: O/ |4 x+ @* G% b+ O

STDMETHOD(Login());

, Q6 J4 {! n% A W) D" i2 l0 Z

STDMETHOD(Logout());

( w4 Z8 c" Y$ w7 Y# Q* \, v3 E

};

0 O7 {9 ]& k6 S* X

然后简单实现之

' i* |8 A9 w9 `- Z

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

: X) i( l7 F% E0 F" u% G7 U8 @

: TCRemoteDataModule(Owner), FLogin(false)

( L" h4 s- M* _2 c

{

- a4 b8 \5 ~. n

}

5 F2 |) e3 `6 Q

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

, Q# Z9 T+ `# [( K

void __fastcall TLoginServer::SetLogin(bool value)

?) d; I4 _ x1 i$ V% O

{

' r- W3 a* M6 b1 s' k9 Q c

if(FLogin != value)

/ K9 ?" Z" M; ]* p" C

{

7 ]3 c5 Y; P1 f) B

FLogin = value;

4 s5 c; L$ C M x C7 b

dspAnimals->Exported = FLogin;

+ ?' l- o# c. L% d: i+ Q" {

}

- S! H6 `; p* e( y

}

3 _0 z! |6 P- q+ t3 F9 z

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

! n, |" F2 O4 P3 E5 c9 I3 S# w1 H3 g

STDMETHODIMP TLoginServerImpl:ogin()

1 g- e! j, X u4 u$ H# v

{

) t& M& i3 v: |

m_DataModule->Login = true;

" c9 o& o1 |) L8 P

return S_OK;

7 i$ q/ T; N5 p3 l

}

2 Z4 K/ O: w, |! U& J1 A1 V/ c! f

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

+ `% N( k7 b$ m

STDMETHODIMP TLoginServerImpl:ogout()

$ |* w' R' P: x# t! C* b

{

' t+ ? w& Z, z; z

m_DataModule->Login = false;

* C+ p, B5 M6 E; r

return S_FALSE;

. g* [6 I0 w. x

}

- x9 E; I1 y1 o: P/ c- n1 g# g

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

2 P" G) j: K" L. y d$ b: T" ~

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

/ E& x5 W9 @2 h3 O# }

{

: w4 @; C4 o: S$ d1 {

return FLogin;

. A* c) R( L5 J$ h3 Z0 _" z

}

) m) y5 A2 P0 l* B3 Q

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

' j( t) K" m' t/ A

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

# `5 V( j' t. r7 R+ T

# V- Z% u: L+ V1 e/ B

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

* |! I9 t8 M' _) M" N7 v* {8 m

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

" T8 i% l9 ?$ i* f& G0 i

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

, s: ~9 K# G: `( p( e3 X4 F+ ]+ X* i4 Y

dispLoginServer.Login();

8 J/ M" [- V, K4 \

DM->cdsAnimals->Open();

) d- P9 b }9 s

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

8 \ W" B- m' C) @5 g! l2 H

5 a2 ?5 L8 w- X3 ?0 v8 p4 W

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

& s& t; I& i: `1 ]: _; C3 w5 r* L

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

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-4-18 19:44 , Processed in 0.331868 second(s), 52 queries .

回顶部