|
$ r/ I \1 h* ^2 g
2. 呼叫 对连接其间每次呼叫进行安全检查 * c9 r4 l F' p0 t% C. i! w6 W6 }+ R
% W1 F9 _7 ]& l/ |/ m 对应于MIDAS中其实就是每次取、改数据时对用户进行检查 9 q, M( I+ B0 o7 O( K( `# ]
因为所有客户端都是通过IAppServer接口对服务器进行操作 3 F; A1 j6 F- H+ U, C! D: ]* F
因此一劳永逸的方法是自己提供IAppServer接口的实现,
* ]9 d. G' E; g1 y/ {, ` 考察一个实例 0 J' m$ r2 o2 ^% Z" A. K! @5 t2 B
' k V) j2 }7 h
class ATL_NO_VTABLE TLoginServerImpl
5 X5 L! }4 K' s3 e# E) a: y% m0 B : REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin . j5 r3 f. p v3 {/ m- S, D9 _
Server),
2 D4 t/ d/ c" O! F: U public IConnectionPointContainerImpl<TLoginServerImpl>, $ M) i4 C, x6 ^1 k) N" V
public TEvents_LoginServer<TLoginServerImpl> 4 w O# v8 Q" q% o8 ]$ Y, g
{ 9 u4 f- W+ W, E, a/ B
... \3 q2 D: Q( K2 O
} & `$ k& I8 T2 [+ u
BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义 # y& }; E; a W" h& F; m5 F5 B
6 l1 u( d7 T* O' P5 B7 y/ s- y#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \
( V' I* B2 u/ W7 q$ P- M public CComObjectRootEx<CComObjectThreadModel>, \
4 h) E+ ^, H0 \) a' t# s0 J: j8 q5 I public CComCoClass<cppClass, &CLSID_##CoClass>, \ 1 T; @: ?- W7 j, m: t. r
public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \
) V8 S' T+ g, @, n, a# ?1 f LIBID_OF_##CoClass>
$ l; J: m" j, h5 w/ v1 b 6 ?& K( D, S( w$ P$ b) e' k, H
这里的IAppServerImpl是BCB用来实现IAppServer的模板类
- U; N* }6 {* o 而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁
/ F9 a" K% y; } 完全可以通过实现自己的相应模板类来实现在IAppServer ( J$ n7 E9 x9 W2 {7 R% b. r
一级实现用户身份检验功能。这样做效率最高,但比较麻烦 ( q& A) A6 ?+ ^/ e/ J0 F: V6 K4 b
有兴趣的朋友可以自己下去试试,这里不再详细说明
* X! o. x5 {3 T5 E: |: Y) E% T \ 5 b+ q, a2 M% k) E
注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData
" b& D% R* \; I 参数,可以通过此参数取得足够的用户信息,用以校验 . |9 @$ z, Z3 {$ M8 Y; v% `. j
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型) / b( T$ { V0 p
然后将之与服务器端已知的特定用户信息一起hash一把,呵呵 " K, g! {) l# m! ~/ A1 g% u' j
/ m& e, d2 [. s* k6 n2 G 次一级的方法是利用现有的VCL结构提供的事件来解决
1 A7 R& Y- ?! ^( _7 F) ~. { 不过这样做就有点麻烦了,呵呵,你必须在所有需要有
# d4 `3 Z B$ G* z* h; d 安全检验功能的TDatasetProvider的基本上所有BeforeXXX
0 C' ?" s9 o- R+ i 事件里面增加相应的安全检验功能,如 , F: u" y" }' J6 A0 z
if(!IsLogin(OwnerData)) * s: X0 m( J& k! P( z7 E B, o6 B5 u o) z
{ 1 D* \4 w) u& _; l5 F2 @2 V
throw Exception("Please login first!"); % [# A- B1 A7 t3 m' u3 p- G# C# I- O
}
0 X' J l. O- E3 Y& K+ r4 L 出错直接抛出一个异常即可,系统会自动捕获返回给客户端 * B9 Y x+ ^+ e% @0 t
好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码
b5 j8 P* X, E; e- ~; Y8 Y! N 而在客户端需要做的事情就是在合适的时刻login/logout
5 ^3 C3 M; n" o 然后在相应的TClientDataSet::BeforeXXX事件中将 , P, e" P" D5 k$ }
OleVariant &OwnerData设置成相应的数据
; @, }8 I% C( B- w
; M! L& L" o8 F2 C% ?0 f4 B5 t 一种变通的办法可以重载你的TSocketConnection类 7 h9 Y) f/ o* m" l& T
将每次对IAppServer接口的调用中的OwnerData加一个
5 l6 \/ p$ t/ i' |& ^7 P 自己的鉴定信息头,然后在服务器端剥离,呵呵 , Z* R* ^0 T4 e) U" k
这个方法有兴趣自己试试好了 |