QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

& H: {3 a- @( A- G/ Q5 e

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

% Q* j* m4 p7 s

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

/ @6 Z. H. i9 g

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

$ C1 \7 t3 v3 y

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

( N; R0 S F7 H8 C2 ]

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

: B( v: i; U* t, X

8 u! y' w- l6 b$ x& H9 A

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

. ]- Y9 B6 u6 X% C5 {' _- B; W

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

) Z q% A' n$ J; x* Q

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

/ r. |" _, Q. H3 i/ Y8 s

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

" @, `7 f3 K) p$ C8 m

! l! O0 E& c7 ^' t/ \1 {! J- q

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

# _" k- A/ F3 C: {, Z: C

! u5 @$ v1 ]9 G2 o

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

1 n v+ S" [8 b1 R8 B- b$ I

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

$ X* T/ u) ]" b6 z5 F: v* q

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

2 u) N5 b+ W/ L5 G) R( O

interface ILoginServer: IAppServer

% ?( ]8 P2 R H- w. T( I* f

{

, m3 `$ @* K2 U9 x

[

3 o" i; U' K! c( i3 c! K5 Q9 w

id(0x00000001)

n- G3 a3 Z' }, l' k6 m

]

$ l% L7 w& h+ ~3 H

HRESULT _stdcall Login( void );

: g0 d7 q% ^" M; U4 ^! j

[

1 ~7 E1 g; h* B

id(0x00000002)

9 ~* t) X- B4 D, g2 z$ x

]

2 q, z2 P8 L" R

HRESULT _stdcall Logout( void );

8 K3 m8 e6 c5 d, [: l

};

. Z1 B `7 _: b6 k8 ^0 X7 I/ R. }; D Q

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

: v* w8 g$ Y# T5 X# @; ]

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

/ e8 O- Q! i$ D5 J

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

/ x1 F3 I/ P- G6 J) v0 {

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

; ]9 W' ?) [. w( R

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

0 ~, z' M7 Z( E J$ Q) v

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

# ?6 M' C" |* e' n) J' `

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

+ j% K2 o4 ]- k( ?. Q

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

! H+ J |' j: V: \( d

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

! F( J' p% F' Y

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

7 Y$ h4 f" W- ~

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

: q2 m- {* G4 l9 @2 G1 G

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

" B! W6 ?+ p! ?( a3 O, ~. G

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

) Z! _+ M' I5 _. M: T9 w1 M

class TLoginServer : public TCRemoteDataModule

( `9 i6 w+ I% U- S; [# W: E' V

{

+ Z" X8 N" C. `, @: J3 N3 x

...

H- X' X0 [+ e/ f' K

private: // User declarations

9 ~" H, n. ]2 H% j

bool FLogin;

+ z! Q8 G6 A7 K" P9 ~( a- x

void __fastcall SetLogin(bool value);

( Q4 N; Y3 @: a; x5 {; b0 H/ g

bool __fastcall IsLogin(OleVariant &OwnerData);

/ f* W8 ^! z2 F) U

...

# `: e/ Y J, I, v8 m

__published:

0 N2 D/ I9 S* L% J

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

7 e) c9 K+ Q" h0 a

};

6 g7 y! s" I7 [, v

在RDM实现类中

7 Y6 m" ?7 a$ c5 i" V6 ]

class ATL_NO_VTABLE TLoginServerImpl: 。。。

# L" n/ l, K- v9 G

{

4 @: ~; H% T, R4 O0 ], f

// ILoginServer

3 m2 k+ k& ]+ v* c$ N* \

protected:

$ O. B) a. F$ C1 j2 I5 Y3 M

STDMETHOD(Login());

/ B- C! E4 ~3 l* D4 A

STDMETHOD(Logout());

' h6 W4 ?: e" I2 n

};

1 l2 E% t6 o# w3 y0 F$ b8 f, k" b

然后简单实现之

* v. t3 e4 v5 `" ?

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

5 G9 z0 t6 W3 H7 U

: TCRemoteDataModule(Owner), FLogin(false)

. \. c3 C( C+ x5 b# R

{

0 ?/ _* Q, U& G, b5 V

}

/ d0 X: \' S4 r. M$ r/ ?8 h

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

S* B6 |6 d' u$ u) C9 q

void __fastcall TLoginServer::SetLogin(bool value)

/ }& B2 g0 k# x1 K m# ~" S+ y7 F( {

{

, ` X: G* L9 a% B8 B

if(FLogin != value)

) S- N3 s ~+ A7 C, t5 N

{

. g# F& y3 Q, `/ P( ]/ a/ v* ^

FLogin = value;

8 U1 G8 _# c' u. A

dspAnimals->Exported = FLogin;

' ?9 K5 ]8 ~3 o0 L

}

7 A. }6 Q9 {( s1 H* b {

}

7 ^2 W c a5 X' p0 b

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

! }0 z: c* \ D+ Z

STDMETHODIMP TLoginServerImpl:ogin()

4 p& `) T( X5 i- V

{

9 ?% V; o2 i H$ D" ]! g: i3 l

m_DataModule->Login = true;

( Y! }! S k1 t

return S_OK;

+ J' |$ X& a: b6 c% \! B$ w

}

( R- ~" d' I' Y1 O/ V5 |

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

0 _/ t) p3 f- v5 a9 y

STDMETHODIMP TLoginServerImpl:ogout()

: }* L) q; H$ t" y! G7 [8 D

{

5 Q4 p, z( c# j% r7 ]$ D: Z: M6 s

m_DataModule->Login = false;

( j: J& b* D5 ^0 o

return S_FALSE;

4 b( L* w/ I) ~2 ]4 M! V6 E- Z+ |

}

0 ], ^, j4 Y* V5 O5 w- B

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

5 _% I; a" {0 H2 r0 c; O3 \

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

$ ]9 q9 Z5 ]0 y3 c# H* z( ~

{

# A, V8 }1 }, g. V( N

return FLogin;

5 c y' D& u$ Z7 F5 p+ ^! @$ K

}

* h3 J0 U- f, q* S% c

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

# b- g) m$ S8 @' t7 V

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

$ p" G( E. y; L! W

# J2 x; S) I# H. _" R; T9 j

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

1 o% I1 a$ P' I ]0 P* n1 J

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

1 c$ W* u- C0 S6 Z1 R4 g9 |) X

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

" K6 k! q$ y* J; O& Z' F

dispLoginServer.Login();

. p9 w9 J$ F! |9 i

DM->cdsAnimals->Open();

( @7 z# e# M+ y& N! w

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

) Y/ b; L8 \4 R5 |1 G

6 |9 y5 D' Q. w: u0 F7 r% I' w3 ~

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

5 v5 ~2 x) _, g) J _$ o. Z- R7 @

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

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 08:59 , Processed in 0.447138 second(s), 52 queries .

回顶部