|
# z/ h) B5 Y- w! [! E
2. 呼叫 对连接其间每次呼叫进行安全检查
) s7 `; k$ o b z
6 S1 m" o2 y$ x" X$ A 对应于MIDAS中其实就是每次取、改数据时对用户进行检查
9 R' t8 F% A( U; S/ V 因为所有客户端都是通过IAppServer接口对服务器进行操作
5 x2 j6 c, _5 \' d6 \8 {/ m& N, D- _ 因此一劳永逸的方法是自己提供IAppServer接口的实现,
" I& T9 T: W* |/ m2 J 考察一个实例 . _1 d1 y: n; }: q; S
0 W1 r$ n( K8 P) s, ^class ATL_NO_VTABLE TLoginServerImpl
- f: d4 @' o2 {" n" M : REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin
" g o4 o B6 V( T+ o& } VServer), ( \% {# W2 t5 D
public IConnectionPointContainerImpl<TLoginServerImpl>, $ H# ^2 S2 \2 p& w R0 \
public TEvents_LoginServer<TLoginServerImpl>
. q. {1 Z% e, y: u( B* _{
: F& k! z8 t4 t' e0 `. d! T...
& t) o [: h+ A5 v} % l% s- M# e" h% U+ k' T6 i
BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义
3 h% q% W, l" A& | 0 n" p7 |6 d: O, R6 m
#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \
; C o7 g, R) X6 z9 F' s public CComObjectRootEx<CComObjectThreadModel>, \ 5 C3 P7 i! k/ S* h; j
public CComCoClass<cppClass, &CLSID_##CoClass>, \
7 Z, p5 B- K4 s# `) r+ Q: O; H' m public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \ * n9 b# g% W! V! _- f8 _% Z1 t
LIBID_OF_##CoClass>
0 U7 Z, X+ M2 b# x# X/ Z% o. d' M 1 Q/ d& p# F$ L, g, N
这里的IAppServerImpl是BCB用来实现IAppServer的模板类 C) T& L3 J5 m4 P8 n6 N0 n
而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁
5 o2 y9 |8 r; `+ F) ]. l 完全可以通过实现自己的相应模板类来实现在IAppServer
8 y) V" w4 Z% z. s 一级实现用户身份检验功能。这样做效率最高,但比较麻烦
! L4 L, u+ ~: v3 g( t- l7 C 有兴趣的朋友可以自己下去试试,这里不再详细说明 # i- N8 f8 c4 f! q* p
9 a+ p$ [/ F6 x7 j1 c 注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData
3 p8 G; }' f# p3 v+ q 参数,可以通过此参数取得足够的用户信息,用以校验 8 e6 E. Q8 }. ~
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型)
( ^2 c0 S6 O& ]7 ?) r 然后将之与服务器端已知的特定用户信息一起hash一把,呵呵
w& N V4 P5 } # m! F! G4 {% m. W' V4 n
次一级的方法是利用现有的VCL结构提供的事件来解决 ' [8 J4 v( x. u6 ] Z
不过这样做就有点麻烦了,呵呵,你必须在所有需要有 0 \) I) m, E. a
安全检验功能的TDatasetProvider的基本上所有BeforeXXX / d! Q; i$ r# |9 M
事件里面增加相应的安全检验功能,如 , O1 X& X! N+ W+ F3 n
if(!IsLogin(OwnerData)) ' H. F# C+ N0 n6 h' h6 ~
{
- I+ [2 ^+ Q- o+ J" ~8 ~7 l throw Exception("Please login first!"); ! I2 q5 M* z% r P- t! n
}
: K' A: P" s \ 出错直接抛出一个异常即可,系统会自动捕获返回给客户端 ' c2 \1 W$ N+ b( Z! A' o
好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码
- s' | v3 g! n" k3 N9 ?/ ~ 而在客户端需要做的事情就是在合适的时刻login/logout 6 P4 ~. n3 _: P, B# b1 H
然后在相应的TClientDataSet::BeforeXXX事件中将 / }) |# _. l& Z. |5 E/ L) u) d, @ m) x
OleVariant &OwnerData设置成相应的数据 # S `5 u5 F) K$ ]) x( b5 D
, V8 d! \1 [5 b$ w8 X3 P 一种变通的办法可以重载你的TSocketConnection类
1 C4 K# R1 e ?9 ^" ~! S1 h& S 将每次对IAppServer接口的调用中的OwnerData加一个
( n! Q4 A; g+ l: I& L: i+ d 自己的鉴定信息头,然后在服务器端剥离,呵呵 c! w7 I+ f8 f
这个方法有兴趣自己试试好了 |