|
2 ?& n- i# S2 h
2. 呼叫 对连接其间每次呼叫进行安全检查 ; M: `( W+ B3 f5 Z! A$ X1 J* |
+ Y- l% k8 i' ^. J4 _2 v 对应于MIDAS中其实就是每次取、改数据时对用户进行检查 : ?, c r3 C: P7 C: l
因为所有客户端都是通过IAppServer接口对服务器进行操作 4 i! g" k* w2 R: r' @
因此一劳永逸的方法是自己提供IAppServer接口的实现, ( Y( L% N: Y) W. o- e: ]& S) P
考察一个实例
1 l# A# S. f) r1 @1 T6 `+ I 8 N8 {' _$ w' { B' y3 C
class ATL_NO_VTABLE TLoginServerImpl
) R' o% |6 s7 L+ d( J$ `5 I : REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin $ l$ M8 Q# A0 {6 T: O0 B8 s
Server),
" T) w) X8 Q3 P# Q( k$ P7 O public IConnectionPointContainerImpl<TLoginServerImpl>,
; c1 h p5 {# ~/ ^; m7 G# J. G! M1 L public TEvents_LoginServer<TLoginServerImpl>
4 g. x0 k* X/ @0 r1 F6 c# F{ . m {( Y" H, s4 v2 _ @, M
...
, I# a/ `" j0 \6 I- |+ w- u0 m}
3 I$ o& H# a% _5 k' O3 p7 Z+ X# Y BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义 - i* ~; j( \/ r y8 h+ I
* K7 R, m. c, n3 N( V3 N7 V7 ?. b+ I
#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \
3 y1 j1 ]8 w! c; K7 E2 y public CComObjectRootEx<CComObjectThreadModel>, \ 9 v4 P7 T3 ^' ]) K! A. D
public CComCoClass<cppClass, &CLSID_##CoClass>, \ 1 }! ?$ J5 s( ]
public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \
) x2 ]7 C6 [1 h% Y LIBID_OF_##CoClass> # M' V* z+ j* _# m- }& F) {0 v
6 h" w3 m6 l* C( J! x* ^; H$ v5 ] 这里的IAppServerImpl是BCB用来实现IAppServer的模板类 7 X& Y9 K3 J* r3 O6 N
而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁
1 H9 E6 i f& B. s( V 完全可以通过实现自己的相应模板类来实现在IAppServer ' t$ [% ?2 e% e( O- x; W1 v8 H5 s
一级实现用户身份检验功能。这样做效率最高,但比较麻烦 4 |6 M1 P8 [9 N
有兴趣的朋友可以自己下去试试,这里不再详细说明 2 X1 I# M) I" n5 w: @7 x$ k: }" g
& l; N4 ~4 O: }3 g$ \ 注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData ; m; k" Z5 x9 A( `" C
参数,可以通过此参数取得足够的用户信息,用以校验 6 u0 t: k4 \3 b/ ]8 C7 L
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型)
. m$ C; J4 B% ~! J( j" _; O 然后将之与服务器端已知的特定用户信息一起hash一把,呵呵
# e+ |& [( j; u% z, O: I/ z3 a
4 T6 s& {9 |! u4 t0 @( G5 P- k2 u 次一级的方法是利用现有的VCL结构提供的事件来解决 ' h, _/ @& d+ j5 s
不过这样做就有点麻烦了,呵呵,你必须在所有需要有
% M) G1 N& I: r) w 安全检验功能的TDatasetProvider的基本上所有BeforeXXX
+ e, L1 w8 K" J% y( p8 f5 h 事件里面增加相应的安全检验功能,如 2 a1 o; b0 D; ?; X4 v
if(!IsLogin(OwnerData)) ( a3 ` A: P; E. N
{ ' A5 |. K* d* `
throw Exception("Please login first!"); 4 o3 h8 k5 e1 f w* L# x+ V' b
} + i6 g8 j, S* n! a5 r+ D! h
出错直接抛出一个异常即可,系统会自动捕获返回给客户端
$ L, D$ S$ K* }, g b 好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码
8 J) D/ N& v$ \/ V- x5 h% f6 \ X 而在客户端需要做的事情就是在合适的时刻login/logout
5 Y$ p( \: G: O% h 然后在相应的TClientDataSet::BeforeXXX事件中将 * ?2 p: \5 D2 I# R. I' d
OleVariant &OwnerData设置成相应的数据 0 k6 D0 W8 V9 j4 k6 [1 E6 p' M& \
% [0 B7 N( C2 L: g! L 一种变通的办法可以重载你的TSocketConnection类 + |4 }; I7 m- K+ n$ K3 R
将每次对IAppServer接口的调用中的OwnerData加一个
# p, _5 D% a. P; M; W; M 自己的鉴定信息头,然后在服务器端剥离,呵呵
' V4 N- R0 A8 d) S( S2 f8 W 这个方法有兴趣自己试试好了 |