|
B# v/ z4 l! U6 h: `# u" d- Q
2. 呼叫 对连接其间每次呼叫进行安全检查 6 r0 E+ u3 o5 k
% z1 Q- O6 R2 U5 u
对应于MIDAS中其实就是每次取、改数据时对用户进行检查
% i$ ]3 x% t# ?& r0 M 因为所有客户端都是通过IAppServer接口对服务器进行操作
' W( s8 Q; ^9 B# s4 ` 因此一劳永逸的方法是自己提供IAppServer接口的实现, , x7 y! u. E3 F" C4 X
考察一个实例
! O! y3 G1 r) u/ B ! A) h, w# `0 G! i; }. j; A6 e5 A8 c% A
class ATL_NO_VTABLE TLoginServerImpl : K/ E' Q$ E6 u: b, X
: REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin
0 h/ E* r" k6 C* Y- M, q+ B3 _Server),
( A$ B5 z# [- Q0 m" n1 _ public IConnectionPointContainerImpl<TLoginServerImpl>,
4 t1 M) ^; W3 X# i2 \/ d& H$ l public TEvents_LoginServer<TLoginServerImpl> ' z8 ^+ _6 l1 U
{
. B* F7 B% H- _1 {...
c' {7 R6 Z- p4 e) Z( i# Q( P} + H7 m: o" M# d z5 R5 L3 U) R; N3 K
BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义
8 J$ M- U2 C% u6 J$ w$ e4 ] ( R1 K/ [4 ~& o# o+ V" t6 a
#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \ 9 n+ _% Y/ {2 y8 m4 t8 h
public CComObjectRootEx<CComObjectThreadModel>, \ 2 W/ W* v2 D4 w2 _4 J
public CComCoClass<cppClass, &CLSID_##CoClass>, \ " l) h# a9 Z2 s& d$ c
public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \ 0 w5 d2 J: a+ F( N% E, w! [# ^
LIBID_OF_##CoClass> " G: R- g7 ?; b6 F% x3 w$ s
& p- o! s B6 Q/ u$ x/ W: d 这里的IAppServerImpl是BCB用来实现IAppServer的模板类
" E O2 j1 d: n6 C! E7 p" d 而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁 b. ~$ {, _8 X2 \
完全可以通过实现自己的相应模板类来实现在IAppServer
! ]! D& j. [3 e4 d; a 一级实现用户身份检验功能。这样做效率最高,但比较麻烦 ) a9 f% N9 Q% z/ V
有兴趣的朋友可以自己下去试试,这里不再详细说明
3 q* f1 p1 w& X- f' B " s g( _& q) h4 r% W+ J
注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData - q& p) m t6 B! i. a- |( {
参数,可以通过此参数取得足够的用户信息,用以校验 ( H0 E9 ]. a: E8 K" s) b# g( h
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型)
# b/ a5 G2 H3 K& W 然后将之与服务器端已知的特定用户信息一起hash一把,呵呵
% I, f( |9 ` ?% ^) o+ z . b/ [. y' Z' c) I5 A' C/ h
次一级的方法是利用现有的VCL结构提供的事件来解决
* {/ c7 n1 t) g5 T! S2 C" }% K 不过这样做就有点麻烦了,呵呵,你必须在所有需要有 2 Q7 L8 d( m3 n1 G* M, y3 H! v# P
安全检验功能的TDatasetProvider的基本上所有BeforeXXX 1 x6 W. N, `( [0 j
事件里面增加相应的安全检验功能,如
$ _, |4 V2 m" w% w3 U8 l, j if(!IsLogin(OwnerData))
; L4 d; X% F" n {
) _: o, v( k3 v, @) ? throw Exception("Please login first!"); ) k+ l6 V- ~" U- ?+ w) J
} 0 l, C) L' l! A7 o8 V1 o- S+ Z
出错直接抛出一个异常即可,系统会自动捕获返回给客户端 . R+ ?, f. g7 \/ Z; M8 h( I
好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码 1 X1 f7 W+ m2 K; C" V4 j
而在客户端需要做的事情就是在合适的时刻login/logout - _1 }& L" ~9 e
然后在相应的TClientDataSet::BeforeXXX事件中将 : l) f) T$ b+ L' [0 ~
OleVariant &OwnerData设置成相应的数据 * v- F+ K ^$ x- G
j/ M& l% w7 U. o& K3 h' a 一种变通的办法可以重载你的TSocketConnection类 * f9 n4 |4 Z6 z9 K( `$ i
将每次对IAppServer接口的调用中的OwnerData加一个
! V! D3 p! n( }6 m; i4 p 自己的鉴定信息头,然后在服务器端剥离,呵呵
9 P. o7 w2 m) N) i0 z 这个方法有兴趣自己试试好了 |