|
: O1 _+ \9 g _" F5 r, Q
2. 呼叫 对连接其间每次呼叫进行安全检查
( x& T) Q4 z6 Q7 r
' H' S0 c) i6 ^4 o/ J4 i2 k 对应于MIDAS中其实就是每次取、改数据时对用户进行检查 # p" q* ~8 ^: \& W, _
因为所有客户端都是通过IAppServer接口对服务器进行操作 / M7 g3 @1 b! v8 @# ]; q: O6 J
因此一劳永逸的方法是自己提供IAppServer接口的实现, . Z' d7 l$ T" u1 d6 r2 [, M- @/ \
考察一个实例 5 `6 {. ~/ `: b! d# a: ?
$ h8 x& X! F" g- }% U" sclass ATL_NO_VTABLE TLoginServerImpl
Q$ C4 P1 B6 A, W% f: \ : REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin 1 E: _8 A. ~! ^& C# y! \- I# ?
Server), 3 u' R" R1 R P6 K5 E& I$ E
public IConnectionPointContainerImpl<TLoginServerImpl>,
1 K& j% s+ n3 K7 d+ q% Q public TEvents_LoginServer<TLoginServerImpl> , M4 W& v4 L6 S7 A; y, v2 m
{ / B* t% s* W( R( v
... 1 @" K1 X* K8 b1 Z; p$ q/ b }
}
) M/ j& F7 b# ? BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义 - X8 ]( u5 r2 |9 V
! V5 ^1 @7 h% T V
#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \
$ f0 P1 }- J, \% t4 D9 L public CComObjectRootEx<CComObjectThreadModel>, \ $ M. a# n% T$ F$ f6 M5 w1 G. ^
public CComCoClass<cppClass, &CLSID_##CoClass>, \
. n0 b' B3 J+ S5 S9 X$ F; M* ~ public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \
. B7 l- F0 P6 T+ v9 c! A' L; e LIBID_OF_##CoClass> 2 v7 }) q, R+ [9 i& {0 t
; l# W( n. |7 V* j
这里的IAppServerImpl是BCB用来实现IAppServer的模板类 2 ^* X7 o& m1 M {9 o8 F W6 w
而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁 : W7 Z. X* ^* m3 ~; K
完全可以通过实现自己的相应模板类来实现在IAppServer
4 a$ O" ?" j6 { 一级实现用户身份检验功能。这样做效率最高,但比较麻烦 + ]7 Q$ p6 r: i7 m. U1 h2 b
有兴趣的朋友可以自己下去试试,这里不再详细说明 + n3 W7 a& O# @8 O, T1 m& G
& ^4 B4 o3 [ [; o' ~
注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData
) K7 {9 w5 x! c3 E$ [# Q 参数,可以通过此参数取得足够的用户信息,用以校验 # k5 i: C' x. h8 l- M
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型) 7 ~' g9 a" p. e. }) G& p& }
然后将之与服务器端已知的特定用户信息一起hash一把,呵呵 , C1 k B2 B8 H) l5 \ o6 u
. }: @- h6 V2 `* f- F8 @; m
次一级的方法是利用现有的VCL结构提供的事件来解决 3 I% t9 O' r; x; c3 t/ {
不过这样做就有点麻烦了,呵呵,你必须在所有需要有 1 e) x+ W" x" U& F; ~& i
安全检验功能的TDatasetProvider的基本上所有BeforeXXX
! M, ?( j5 n+ X5 g8 o 事件里面增加相应的安全检验功能,如 ! t' f1 K. K2 ?' B: G
if(!IsLogin(OwnerData)) & l; [/ Z. S7 e$ \9 W$ ^9 v F
{
& O6 x) k$ d, ?6 v; Z$ G throw Exception("Please login first!"); + x8 F# l2 I$ ]/ e# x" d! V" C& w
}
% g6 n+ _# H: S) @# } 出错直接抛出一个异常即可,系统会自动捕获返回给客户端 . a* R9 t9 h- N0 B7 \; S
好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码
; u! m, e: k3 J6 U, u1 ] 而在客户端需要做的事情就是在合适的时刻login/logout 5 w- O3 }3 _# Q( D3 W
然后在相应的TClientDataSet::BeforeXXX事件中将 % A2 p7 e3 P T! q6 ^+ T1 J. D
OleVariant &OwnerData设置成相应的数据
5 V' u! r Y4 @+ h& r0 Y* u & f% R6 Q) J8 l- }
一种变通的办法可以重载你的TSocketConnection类
3 ^: x) G l l+ S4 b 将每次对IAppServer接口的调用中的OwnerData加一个 : m) A) K2 J" L( i- Y
自己的鉴定信息头,然后在服务器端剥离,呵呵 5 ?+ c" {3 A) y) j
这个方法有兴趣自己试试好了 |