QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

! U) @; z* O% B+ B( g

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

4 {0 g! {; f, D u

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

" l+ Q# q( `/ s; p& e

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

3 k" |# w: |6 R h, q

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

9 J7 \$ G+ [ ?

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

2 b* N- x- u) c' ? g& J/ c- p

4 D# K6 Z! w2 F% m

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

" M! u$ p7 K5 Y% p: W

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

$ E. G; J3 S- X( ^

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

1 @! H+ _- f' _* P7 Y- }' [; F

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

P6 X* H9 c8 E' ~* @# n! }+ S' {- L

7 r' O* D7 p D! x, F4 Y& b5 W

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

* _- s7 c% r/ X; E

& |# w; y7 e; w& g( g

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

7 ~5 e& W- Q* U }% o

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

6 w7 U; \8 }1 o7 G9 d

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

$ P' S/ ]" [+ q) J

interface ILoginServer: IAppServer

2 v" y D- n2 ?8 Q

{

+ Q! o* D1 z" Z# X% f8 O, `% m

[

: W$ n, \3 m! l$ g- g e

id(0x00000001)

9 k4 s' P! e6 f+ V$ e

]

" m. K4 O' y" Z: g4 W* a

HRESULT _stdcall Login( void );

) l& d. Z3 c D" O9 ~1 ]* W, A

[

5 j+ y) [ \0 f, o9 c$ W

id(0x00000002)

% e. H1 ~) f3 `6 r/ C* j1 E, m

]

3 { x% V1 r/ k6 J' g

HRESULT _stdcall Logout( void );

- ~8 n1 Z0 O5 t! c0 O+ r2 U

};

$ v) o, P% U2 c5 c; K

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

J3 a, w8 G1 A5 T$ X6 I

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

' i) ^( X- L3 X. K% B! ^

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

4 x* g3 p' L8 s7 }% K

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

3 }% j) p: C) }3 u) Z3 s

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

, n) M/ U7 v3 }

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

9 z8 }% w5 ], W! a! o

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

! U! Q# y. a1 _6 }; `( i

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

# o+ q& y. m8 A( y* v

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

- g2 M/ m7 U& i. I

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

4 ]! n s+ s- s# K) ?5 `

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

) a& e/ j# B0 w3 c# T( ?) r

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

: ^/ y! _% k0 C/ {0 B

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

) K% P' @' ]7 Z1 j4 u/ H- G% x; m7 b

class TLoginServer : public TCRemoteDataModule

: Q7 W1 }; R# K) m0 W' ~

{

3 [/ Q- h" i% R

...

4 G r4 j. T+ m! e) _& _+ Q0 n

private: // User declarations

, J* X3 n4 p0 q; a

bool FLogin;

; z- f. y- V6 U

void __fastcall SetLogin(bool value);

5 ~: @! G J$ e. {

bool __fastcall IsLogin(OleVariant &OwnerData);

$ E4 b" x% Q2 T, d; v C6 T

...

- D2 ^; h+ F' H; N5 z' x6 @* C

__published:

% m2 t, F1 h, ~: E

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

. S- g1 C9 }4 H! B# o5 t7 v

};

# B3 A( `( u& _' q4 E* K# I9 n

在RDM实现类中

3 ~' K9 |4 q& i% D$ g H3 v5 p3 } |

class ATL_NO_VTABLE TLoginServerImpl: 。。。

3 ~: p# \7 d$ J9 K. Y

{

6 C9 v: p4 q, G8 G$ D( C& w* q! [8 S

// ILoginServer

0 G) x5 F9 H4 w4 p

protected:

! B4 h7 k7 J: [/ j. ]3 v7 p

STDMETHOD(Login());

6 k# m' W( F. `

STDMETHOD(Logout());

$ x, `/ F: N9 n4 }- ?

};

% f+ A a+ z3 V" J2 e

然后简单实现之

& e6 u8 H* C. u6 Y! v- X

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

# p1 d7 O+ s: M4 p. ~2 M: Z

: TCRemoteDataModule(Owner), FLogin(false)

* t$ m; p3 R; t6 s; g1 r

{

# d# @/ r* b4 e; a+ ], x

}

. E% l" V: x, }; F

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

, m) p) j( v7 W7 j. o+ s' B

void __fastcall TLoginServer::SetLogin(bool value)

d) j- e/ M% D9 w

{

* U# E9 b- @. o2 q

if(FLogin != value)

, P! v" t S3 ~! A8 D& H

{

+ j9 m6 c0 p8 w3 M

FLogin = value;

* m3 g2 V/ }( V1 Q8 M8 o

dspAnimals->Exported = FLogin;

; L! m0 d$ {& `2 Q# S0 S' g \

}

0 j3 i, M" O2 G; U/ e( a& @6 r3 N

}

6 Q1 T* X4 X6 t3 D7 C# Z& s6 e

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

: k" h t: V: v* g1 b; j

STDMETHODIMP TLoginServerImpl:ogin()

; N! A i/ }/ g8 I

{

: h+ R6 D% K) @3 `8 o

m_DataModule->Login = true;

4 R+ D! S0 m$ v' V! c, `) Z0 |4 p& {

return S_OK;

# s# l+ a0 k+ j) v; M" o

}

- g2 ^: y5 c4 c7 G/ |

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

T7 [8 |) B9 y. }

STDMETHODIMP TLoginServerImpl:ogout()

' a' T1 M) h, j

{

% w1 ]: N: Y3 x0 E1 R H

m_DataModule->Login = false;

% q" I; K/ ~: A; G) d5 `; [

return S_FALSE;

7 E5 N! U" ?& c9 ?0 y/ G4 U

}

* ~& `( X t9 v3 g* B+ {9 r

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

& P. b4 ~$ }( c: n" }# L7 O9 G

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

. o$ @7 d4 l! v4 u8 u

{

( x4 r+ N# _2 N$ j e

return FLogin;

% \3 N; y+ i+ E

}

q9 Q# ~( b4 w' _- m

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

. P r) w! V6 G3 K7 E; T* f* P8 b/ H

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

" l: |! ~3 t% Z: ] Q! @) `

2 Z8 |7 C( f" V1 P" |4 A+ ~. O% t

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

( b0 H$ m1 }1 I0 Q Q0 F

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

6 m0 o/ ~5 P8 E4 S

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

6 `5 Q* [% F' J+ O6 h' z/ l

dispLoginServer.Login();

/ g, _- N1 N5 N8 N

DM->cdsAnimals->Open();

# B4 l+ Q# V8 i) K! O5 L1 O' Q

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

- U3 R3 B) R, q: p! x

8 `" c2 ?6 X5 I; {8 L/ Z( D" K2 d

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

5 m, ~/ X) b( a" m7 C

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

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:58 , Processed in 0.432228 second(s), 51 queries .

回顶部