QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

3 R5 l* w8 `2 Y1 n; m V

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

$ I3 T2 `; G S1 y' a

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

, x- ~1 |+ L% V+ g& F

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

% Y$ A' B# E4 P' r: p

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

! Y8 B/ Z3 K$ C, C

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

# p; J. R- E, T

5 x4 @+ u! @8 |& [1 R& V; S

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

- f: z# B+ I' V3 O4 R

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

7 Z$ F# x6 J4 |& q4 s

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

+ v- B% a; l) M" K8 [

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

* {5 ]7 b7 i7 O d3 w f

& d2 b* U5 k/ x# M+ |" G

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

& F# B% s+ f# Y. a8 k: T

( p2 [. a3 s5 K# @: B# `

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

6 z* U Q: ~( d$ g+ s8 a

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

7 w3 e' M4 M4 d. h# l

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

# o% r6 [) v: w; s& K9 }* X

interface ILoginServer: IAppServer

2 M8 z6 y w( s' C5 p3 _" ^8 M

{

( J( M2 G9 N, D% i; {5 R1 B. G

[

H( @1 X8 p! w

id(0x00000001)

. _' W ^+ u3 _3 l

]

m$ Z( M9 x, i/ ]9 e

HRESULT _stdcall Login( void );

. u% X. I: u2 r' o, i

[

$ e: q4 w6 i: ?& s5 T: a' W4 l

id(0x00000002)

% K+ Y* T% g* k6 V" g9 g7 i7 U

]

/ L9 J* v% Q- k* T. R! h* f) M

HRESULT _stdcall Logout( void );

6 Z: D8 A, v* A/ G. S: g0 b) x

};

& m: y' j" l: C5 g9 H$ K2 s) [

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

& v& _" _* k: T& i

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

9 v) H* I b, {- g

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

1 K/ Y& i$ t4 q- N% {

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

3 D( Y, P- d4 f+ q% i

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

7 h( S- y" _3 _ B l) t

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

3 ]9 [. H6 [: k+ P% y I

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

1 [( o h; x5 n! S+ ^" t

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

$ F& Y# n- d! H/ x& g) h

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

3 V$ `9 B7 O# u1 y

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

3 k+ p6 F7 M* _

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

- H) a3 S E' B; N- k2 F6 q' }

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

" v y% H$ u- P% i

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

- R$ u9 @& u: ]

class TLoginServer : public TCRemoteDataModule

+ t' `+ B5 `9 e- n1 n- I4 h) U

{

; K6 I1 `- v3 i

...

' Z9 U' Y7 e# q, H" i5 L

private: // User declarations

, ^1 r q6 w) V$ A

bool FLogin;

4 s, T4 e2 I6 ?- Q0 @

void __fastcall SetLogin(bool value);

% a; Z6 ~- J4 w6 P' |8 ^8 {

bool __fastcall IsLogin(OleVariant &OwnerData);

. t) e& ]/ ~9 D# }5 m' C# x8 I4 h, A

...

5 `5 R6 I2 a3 u5 G$ x% N' _

__published:

) q6 {5 I7 _. V

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

* C' R3 w. P3 [+ x; W

};

o+ [0 ~0 G& i. Z2 r/ @* a+ Y) Z

在RDM实现类中

( V. v9 x' q; }3 {6 J3 I$ N4 c

class ATL_NO_VTABLE TLoginServerImpl: 。。。

0 D; R. D* f7 V" e* @5 `

{

7 F3 e: o! c6 k$ p# j- }% M4 }

// ILoginServer

/ w$ p7 X! Q$ M! M

protected:

5 k7 G' I3 t! _

STDMETHOD(Login());

( g; h* k& f3 S. t, F% c: v% Q6 u

STDMETHOD(Logout());

; g6 i$ y+ Y. w7 }

};

- D( c! D5 D: L7 W

然后简单实现之

& |' y9 V4 ]; b3 c$ C, O+ Z

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

( s( F/ b( J- v G

: TCRemoteDataModule(Owner), FLogin(false)

+ s! M& Y2 i6 r) C5 Y$ G7 S! V+ ^

{

: q0 j7 w6 j1 n, J$ y; @

}

" n2 |" b+ e- F: H" T, k1 v

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

8 M8 {/ s' k3 j3 F' R" j8 f

void __fastcall TLoginServer::SetLogin(bool value)

$ ?' m. c* s- v1 n' X. h

{

" c8 i! W4 C8 D2 z0 L+ {

if(FLogin != value)

! t8 B8 k/ c" u- _5 F) q/ h( I

{

7 c9 e; |, q& u- c$ Y9 O

FLogin = value;

( D, f9 A/ Y4 X+ E3 ?

dspAnimals->Exported = FLogin;

5 H) W& ~ Q1 x2 a8 z

}

+ i0 S+ \5 [# _+ X! i: U' W

}

0 P) V! [. g& }& t

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

9 l- B8 z& X& b6 f# p, g

STDMETHODIMP TLoginServerImpl:ogin()

+ l* w6 I$ R: G# [9 _

{

# ?3 x1 W$ ~( B: Y V, i7 f

m_DataModule->Login = true;

" s6 E8 c) C, [$ j8 F

return S_OK;

( s# B& F. C8 ~. D

}

$ [9 i4 s: n+ a% ~' Z7 ~) B

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

+ M4 T0 B$ K! P3 `# C2 O2 z2 v

STDMETHODIMP TLoginServerImpl:ogout()

% Q/ P6 Y0 F9 }( m& `% b

{

" u" E) e/ R7 }

m_DataModule->Login = false;

& W1 p q z1 U1 ~( y" L

return S_FALSE;

# u: U6 F' C+ P8 r5 J0 u

}

# [1 |5 w* u7 b& K% ?" c

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

, O2 u* I2 |1 k5 I1 M' L; A$ Q, [! ]1 N

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

7 u3 ?( I3 ` Q- m2 A

{

3 t6 x2 d: z$ N; M

return FLogin;

1 x( ~7 _9 U+ U0 d5 x7 s# t

}

o! n- I5 \3 z$ U, s0 }7 e/ [

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

5 Z" Q( f4 X# \

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

4 y* I2 h; t+ i' `6 N$ G& e5 I

9 E" S* x* j7 [, |* V' j

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

; e* f3 G3 d& n$ `/ d

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

8 x; s. b% k' u0 Q

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

1 q! C, c) H, c& |

dispLoginServer.Login();

# G& }" }5 n" `: {! k

DM->cdsAnimals->Open();

4 X {, x1 F- ]) C

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

, {* U# g- F7 M; E

. R& X, |7 G& t) R' s& w2 T7 i# F3 c

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

2 n6 X' ]' g; g1 @3 X2 E9 M& s b% h

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

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-6-11 01:59 , Processed in 0.439953 second(s), 52 queries .

回顶部