|
5 I( Z" _! q* m# D: ^1 E
2. 呼叫 对连接其间每次呼叫进行安全检查 " I% a! z7 u4 | U8 ^* {
; N+ R( e6 Q) c6 w3 J
对应于MIDAS中其实就是每次取、改数据时对用户进行检查
& E% o% a, r6 v2 ^2 ?$ H7 t# @ 因为所有客户端都是通过IAppServer接口对服务器进行操作 5 i0 H! {3 t) R- l3 Z
因此一劳永逸的方法是自己提供IAppServer接口的实现,
) Y9 V* h' V; ?1 u q 考察一个实例
9 l; o T k. L- m0 X; {3 F+ V
- @; n B2 R7 P4 A* [class ATL_NO_VTABLE TLoginServerImpl
) B4 G% H) u0 l$ \6 C7 ]1 z" O8 x : REMOTEDATAMODULE_IMPL(TLoginServerImpl, LoginServer, TLoginServer, ILogin
$ v# r" M; o4 I7 l+ W" v6 CServer), 8 T2 \1 ~5 B- i; m7 |3 j& {
public IConnectionPointContainerImpl<TLoginServerImpl>,
: q# ^: n+ X9 v) T4 R6 H- M, w7 y public TEvents_LoginServer<TLoginServerImpl>
. v8 D& u. A( X. ?{
& ^4 P7 e$ _! S7 G5 l- X |0 I...
8 L* [5 e) E% m}
! ?6 d# j. _. B& a$ `1 P BCB中是用REMOTEDATAMODULE_IMPL宏封装了IAppServer实现的定义
% @3 O" k7 ?0 i ( M, H" Q1 o6 S
#define REMOTEDATAMODULE_IMPL(cppClass, CoClass, VclClass, intf) \ ( c P' V' h8 P% j. D% I! g7 v
public CComObjectRootEx<CComObjectThreadModel>, \ . Z8 r7 ?9 M$ x4 ^7 B9 t
public CComCoClass<cppClass, &CLSID_##CoClass>, \
: E! c2 U( X$ _- x7 e- Y public IAppServerImpl<VclClass, cppClass, intf, &IID_##intf, \
& M" d9 o% c- w) B( C LIBID_OF_##CoClass>
( R2 k$ `5 e0 u. p" p/ d0 f) X
! a5 r% N4 @& i- n6 N9 j: U, m( e/ g 这里的IAppServerImpl是BCB用来实现IAppServer的模板类 4 j: q. K1 v- z) L6 W- l" g
而IAppServerImpl的实现代码在atlvcl.h文件中,很简洁
; s* Z4 G/ Z# a: a 完全可以通过实现自己的相应模板类来实现在IAppServer
k- S) O" ^" f- k 一级实现用户身份检验功能。这样做效率最高,但比较麻烦 $ `4 g; c' T9 R, Y! f
有兴趣的朋友可以自己下去试试,这里不再详细说明 ; K) Y1 e; K# z& Y
# L9 _( A* E$ t- f) k' i& y 注意基本上所有的IAppServer方法都提供了一个OleVariant& OwnerData
0 y a; k. t: i' A6 c( b: a; v' K8 q$ K) f 参数,可以通过此参数取得足够的用户信息,用以校验
. O$ p, U+ {% D# z( {0 `1 G8 p 比如偶比较喜欢给客户一个实时生成的SessionID(GUID类型) " C8 x I4 E" B; O
然后将之与服务器端已知的特定用户信息一起hash一把,呵呵
: g h0 c2 h0 g, s) d* `
6 W- t2 j8 Y: Z" K7 t7 P5 A 次一级的方法是利用现有的VCL结构提供的事件来解决
$ }! ^8 k1 `7 B3 i5 M) [% | A 不过这样做就有点麻烦了,呵呵,你必须在所有需要有
p4 @4 w b2 l( L" }, h# r 安全检验功能的TDatasetProvider的基本上所有BeforeXXX
. ~4 W; J: V; z 事件里面增加相应的安全检验功能,如 2 d: `- g! X7 e6 b {
if(!IsLogin(OwnerData))
/ @( w1 z% q6 a8 ~: y { 0 B5 j" \5 {0 U0 e) [$ N8 ^$ @
throw Exception("Please login first!"); - d) w) X5 D6 X
} ! M" l/ O$ f( D9 U, x; G K
出错直接抛出一个异常即可,系统会自动捕获返回给客户端 . t ?3 E: b8 s$ ^4 c" S% m) Q3 @
好在大部分的beforeXXX事件都是TRemoteEvent类型,可以共用一段代码 ' y# K' ~' [) t6 g
而在客户端需要做的事情就是在合适的时刻login/logout
" ^% t5 z5 I- I% Z/ k 然后在相应的TClientDataSet::BeforeXXX事件中将 / h3 Q$ m# z/ E2 D- Y8 O6 Q
OleVariant &OwnerData设置成相应的数据
1 K+ \$ K3 ?8 _9 N9 w
: z- _- I! ?! j# I2 F! H* V 一种变通的办法可以重载你的TSocketConnection类
7 n1 r7 [7 g- Y/ y5 E0 V 将每次对IAppServer接口的调用中的OwnerData加一个 4 k3 p! d* ~9 Y9 ~
自己的鉴定信息头,然后在服务器端剥离,呵呵 : S% L: p( R/ B
这个方法有兴趣自己试试好了 |