QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

( |6 D5 n3 f7 F& S4 L' T! u, x

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

8 x# K# N8 }3 d, ]/ f

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

9 E; e1 T* O& b+ h

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

1 J1 O( P% [2 x6 U8 \# m) i

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

6 T+ L1 z. [4 }

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

4 V* ^+ C: Q) N, F

3 z: p; \+ z5 \0 R# S- {! Q8 w3 ~

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

& ^6 x6 L; D: _, t( |

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

7 C: \# s0 ~. C! ~& b2 h

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

5 Y: a0 E+ m- F! e8 U

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

% P+ `4 g4 S& m$ r4 M# g; _8 x- ^2 x

7 G# {# Q! k$ R _$ d% E

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

0 W+ f1 p0 x% l& }! Q1 n

( i7 b2 g) m) c! [6 |* d

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

/ p/ w. ^) c/ K, [4 e8 l$ `

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

! W4 T1 z J- P$ X- z

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

( }( O' @& q$ F* G1 H

interface ILoginServer: IAppServer

8 F y. }( ^1 Y8 M' M; y

{

8 W8 o% q2 b, E* `" f# _. Y! `

[

1 _0 p8 b$ k0 I( N

id(0x00000001)

# u# M) `5 `4 }; V# g8 m

]

( F- [8 B2 O6 G0 r9 F2 Y

HRESULT _stdcall Login( void );

u1 t+ D: o2 K" q" S

[

# C7 {3 v. t0 t3 Y0 F- P

id(0x00000002)

* i6 a/ ^- l3 c3 J

]

$ ^+ G0 {0 M$ d- L; a

HRESULT _stdcall Logout( void );

; {. S' g; V" Q4 v4 `) A) `

};

4 `2 W6 [$ z- b7 t

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

! M8 i" [7 X8 V4 E

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

- s f2 {0 |1 e \7 D

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

% {0 H4 x9 ]; T

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

- z1 p- b) S0 @8 M

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

@* K0 H" P2 K- E8 N

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

# [0 r0 O; ?3 N( ~

virtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in

. s8 t: L5 J# G

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

4 R8 r) u" y$ B' q0 g) ~$ [

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

& y; O# j7 D, y0 }' H) W

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

( ~ p% K f1 m- K( V( T

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

, z. l9 b1 o% @+ Q1 I0 S- K

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

3 B5 g4 c; d+ H/ f9 D2 E( F

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

, t9 ?3 ]9 l) n. z0 v" O" M

class TLoginServer : public TCRemoteDataModule

. d, H3 ~* g2 k( B, u" _

{

+ Z; V! o7 X6 `' s% h

...

; _7 }- \& J' R% B

private: // User declarations

, n- K& V6 U$ t+ T6 r

bool FLogin;

; Z5 c& t& Z+ l' S2 B

void __fastcall SetLogin(bool value);

) |7 c" T) T" `' o0 P! [7 \9 E* g

bool __fastcall IsLogin(OleVariant &OwnerData);

+ C+ o7 s8 o4 u

...

. |% j4 u2 q9 O# A

__published:

' e& P8 i G- ]1 ?

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

a' _" O' e# M) G

};

$ j' `, x) `5 m+ e( D

在RDM实现类中

" E' J5 u/ C9 l

class ATL_NO_VTABLE TLoginServerImpl: 。。。

3 Q1 b2 ^. k9 C8 {/ u5 U3 c

{

% o1 i1 t3 G. L% x! [5 L: G) B

// ILoginServer

w) P( a" o/ K; |$ d1 ]' G

protected:

7 R4 \: k' {9 X+ C! ~; t

STDMETHOD(Login());

+ [7 _! ]3 n& a/ N1 J9 X. Z

STDMETHOD(Logout());

% t, ?6 k: g+ {

};

5 P) m' q; M1 v* |

然后简单实现之

) }3 B# Q) T; z m- `

__fastcall TLoginServer::TLoginServer(TComponent* Owner)

, \# [7 B0 E* _; A3 B* `

: TCRemoteDataModule(Owner), FLogin(false)

J( q$ \# O9 |- S

{

6 p' [! O4 w, M0 Y

}

2 }& W% j; U& ]0 x, `

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

2 M! Q# E/ `/ W J

void __fastcall TLoginServer::SetLogin(bool value)

; C9 z3 O6 m2 k" E G2 X1 Z% r

{

5 C0 j5 r4 |" u: b9 G5 r

if(FLogin != value)

5 T9 {2 x( g- X' ^) v# r+ L

{

8 h, Q0 ~. E& T% U+ Z

FLogin = value;

: ~, @/ \1 \+ s" W5 b+ i. `% n

dspAnimals->Exported = FLogin;

, }9 y5 p* o# j: @6 d( e b

}

. e5 p! T7 I- Q9 s% ~4 P S

}

/ o, Y3 r Y7 N. \8 U& t. u

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

9 P6 p4 b& ?, _: ]8 V9 \6 d7 [

STDMETHODIMP TLoginServerImpl:ogin()

( O' g9 C8 o" }+ n$ L

{

+ I9 E# m" ` n3 c z- h R

m_DataModule->Login = true;

7 P$ O, U3 o3 b: H

return S_OK;

C! W7 [) h9 V$ t+ {9 b

}

( N- J: u- X& V; d: D- W9 a

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

: {5 i7 S$ {0 \; g c8 Z. l: ]: d+ L

STDMETHODIMP TLoginServerImpl:ogout()

6 \0 d* s9 o" ^

{

% r! B- b" ?& x

m_DataModule->Login = false;

/ O8 V0 S' U/ z7 B6 U8 a

return S_FALSE;

! x- | ^! U) {3 ?: M5 Y) L% B

}

/ R8 e( K- ?$ A( s

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

: N2 x1 H4 }. h& U. I n

bool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)

; s' K2 K4 ~/ B" R

{

& s1 x5 ~ K" o% K

return FLogin;

! P& H$ D+ O0 h( y, i/ {

}

7 Z$ w9 C! n5 \4 D1 C9 R: h* V

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

4 I( X* @* P `" l) N( v/ j

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

8 U. t, ~5 z+ j* {2 P$ w7 w

( C8 W. O/ b# f1 F; W+ h

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

4 t8 P6 C! B9 H. R. I. k, E; E, |( ]5 @

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

j% W X4 E( i' @+ {

ILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;

& j# v! u/ l4 F" S+ C, V

dispLoginServer.Login();

' t# N, f+ H! Z+ u) \$ o5 @

DM->cdsAnimals->Open();

& L' g+ q5 @3 v' d

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

) \8 q& u6 S5 { G5 [( x3 ?

+ x4 ~1 N% H1 ?/ [$ ~9 o

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

* f- Y+ i8 r$ L; B+ N2 T7 X

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

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-20 07:43 , Processed in 0.633142 second(s), 52 queries .

回顶部