|
i8 j& K1 E/ X( T$ l, H9 a: J. j9 D
2. 呼叫 对连接其间每次呼叫进行安全检查
, I/ v q6 W$ d. w X3 Z 4 H8 W2 ~0 ^8 _8 J3 y* }
对应于MIDAS中其实就是每次取、改数据时对用户进行检查
' d L$ f* |. g% s3 W* [3 t- {. J 因为所有客户端都是通过IAppServer接口对服务器进行操作 6 ^0 F0 d- Q4 q' `' J
因此一劳永逸的方法是自己提供IAppServer接口的实现,
. [, i" H3 F7 O$ J 考察一个实例
' @) _9 f) {/ I, f8 U; x: Q " s+ J7 _. D" V7 U% Q5 X! ?$ _; ^
class ATL_NO_VTABLE TLoginServerImpl % _/ l, |! C; V E8 d2 Y
: REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin ! f, Q0 M' F; h3 |3 _
Server),
* m2 x. m1 [# \5 s% m! g* ~) } public IConnectionPointContainerImpl<TLoginServerImpl>,
1 @5 t# U d# u' ?3 N4 h9 h public TEvents_LoginServer<TLoginServerImpl>
5 \: n: Y( E) N) W{ + g4 c# Q5 }+ w7 o: D; @
...
8 y# @3 r7 R' U& I R0 x}
$ \; Z5 b' P' w4 l BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义
! v' G: C7 `, ^$ p
: I! Q1 T( m" c2 B#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \
7 T& i' L/ ~0 ?6 S; o: A& T public CComObjectRootEx<CComObjectThreadModel>, \ $ C! G& B6 }; j" t6 I
public CComCoClass<cppClass, &CLSID_##CoClass>, \ & P1 d: h7 a5 C4 |9 ^
public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \
/ v0 k# N5 q( x* u' J' k LIBID_OF_##CoClass> 4 v$ F2 _! Q7 t6 a6 u% `. Z" J
$ s& I4 n( d, n+ }$ g& s# R 这里的IAppServerImpl是BCB用来实现IAppServer的模板类 * }! ^5 |0 g* Z/ X
而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁
* H" u" s [5 R 完全可以通过实现自己的相应模板类来实现在IAppServer
% @, B% A' A: D& n) u 一级实现用户身份检验功能。这样做效率最高,但比较麻烦 & T& g8 ]) ]3 ?' |4 E
有兴趣的朋友可以自己下去试试,这里不再详细说明
$ K2 t* \. `9 K1 t 5 s% B0 G7 o0 J8 b1 e
注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData
; w2 ]/ ?4 ~! ~7 n8 } f$ ~4 D 参数,可以通过此参数取得足够的用户信息,用以校验 , R: [' H7 S9 [
比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型)
, n, v2 y6 ]' y& T6 t" A 然后将之与服务器端已知的特定用户信息一起hash一把,呵呵
1 f* H8 p8 L/ i5 w6 E' ^ b0 G ( @+ v, `7 @6 b) n- c, ]6 @
次一级的方法是利用现有的VCL结构提供的事件来解决
; B4 d& Z' e' }" x* t 不过这样做就有点麻烦了,呵呵,你必须在所有需要有
+ m! W' A! P6 g; I 安全检验功能的TDatasetProvider的基本上所有BeforeXXX % R* K& B" ^& U
事件里面增加相应的安全检验功能,如 # g, k+ y) {* r9 r4 S ~$ p5 y
if(!IsLogin(OwnerData)) $ K; \) l; M2 M; y
{ / o" R; P) O/ R+ k
throw Exception("Please login first!"); ) w M* j/ i) ^. o2 [8 G V
}
- V" j% b K5 y$ S6 ^* A1 D 出错直接抛出一个异常即可,系统会自动捕获返回给客户端
" f s& u; O; T4 C3 d2 w6 W 好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码 ' n9 f+ X5 o# j( ]7 U
而在客户端需要做的事情就是在合适的时刻login/logout 6 e6 h' u8 g. N$ {" ?0 Q% a4 V
然后在相应的TClientDataSet::BeforeXXX事件中将
O3 ]+ H' S# ]: F' Q OleVariant &OwnerData设置成相应的数据 6 r9 C1 _) ~% K0 B) v$ i
3 P, l& r( m( U0 Y: p
一种变通的办法可以重载你的TSocketConnection类
, Q# \0 s9 @$ X& n9 ]6 m 将每次对IAppServer接口的调用中的OwnerData加一个
) I$ @" j2 k, S8 M 自己的鉴定信息头,然后在服务器端剥离,呵呵
0 V8 }% G' J2 K* ^# d 这个方法有兴趣自己试试好了 |