论坛积分策略 论坛VIP区开放申请 我爱电脑万人签名活动 原声大碟520欢迎你 广告位招租
发新话题
打印

[java] 动态Proxy与Java ACL用户访问控制机制实现

动态Proxy与Java ACL用户访问控制机制实现

用户访问控制(Access control )机制总是围绕粗粒度和细粒度两个方面来讨论: www.520diannao.com- z  Q+ Y# e0 f' T, _+ V4 `5 J1 K

$ G9 q) U* ]; K' @我爱电脑技术社区--打造最好的电脑技术自学交流平台
$ r+ D/ L( H/ `( y$ V我爱电脑技术社区--打造最好的电脑技术自学交流平台粗粒度控制:可以规定访问整个对象或对象群的某个层,而细粒度控制则总是在方法或属性层进行控制,比如:
" ?3 i7 B9 @/ y! t" ]) k我爱电脑技术社区--打造最好的电脑技术自学交流平台打造最好的电脑自学交流论坛# R. z  p. H) r. D
www.520diannao.com$ `+ V% p6 g* i7 Y/ M  G! e
允许一个文件为只读是属于粗粒度控制,而允许对这个文件某行有写操作则属于细粒度控制。
5 }. X) R  x! l. G- m4 M# w
' w# Q* R8 @  {电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站  w+ h7 u  c! Z1 b; F/ `
一个好的用户控制机制当然既允许粗粒度也允许细粒度控制,在Jive中我们看到是使用Proxy来达到这个目的,但是我们也发现,由于需要对每个类都要进行细粒度控制,所以必然对每个类都要做一个Proxy类,这样带来了很多Proxy类,如ForumProxy ForumThreadProxy ForumFactoryProxy等,无形增加了系统复杂性。
* C+ A- O  O9 o- H% r; v我爱电脑技术论坛
2 H: f+ t0 {" j8 ]/ L: D$ A
) |# [. o3 u- Bwww.520diannao.com使用动态Proxy可以很好的解决这个问题。再结合java.security.acl的ACL机制,我们就可以灵活地实现粗粒度和细粒度的双重控制。 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站6 i7 R' E- l4 Z8 L. @3 w& l- y

7 b0 L# U2 u. \$ `1 [www.520diannao.com9 G2 f. u" s% s5 t) i; \
当一个用户login后,我们就要在内存中为其建立相应的授权访问机制,使用java.security.acl可以很方便的建立这样一个安全系统。
: }; e* q" O' ^! lwww.520diannao.com
8 @, _6 J" j; O4 E0 p4 a5 Q- f我爱电脑技术社区--打造最好的电脑技术自学交流平台
" a0 I( i* }+ u+ w: |电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站首先任何一个对象都应该有个基本属性:拥有者 或拥有者所属组(Windows中每个目录安全描述符都由4部分构成:对象的创建者、对象所属的组、自由存取控制和系统存取控制)。 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站& E  ]4 Z% r, _- j9 S8 K
打造最好的电脑自学交流论坛4 H, {# C% T% N
1. Java acl开始第一步是建立一个主体 Principal,其中SecurityOwner是主体的拥有者: private static final Principal _securityOwner = new PrincipalImpl("SecurityOwner"); 我爱电脑技术社区--打造最好的电脑技术自学交流平台5 S- u3 r3 a( j5 `* x1 k

2 Y, U: Y5 ]/ B4 [www.520diannao.com2. 当用户login进来时,他带有两个基本数据:访问密码和他要访问的对象ApplicationName。首先验证用户名和密码,然后从数据库中取出其权限数据,建立Permission,这里使用Feature继承了Permission,在Feature中定义了有关权限的细节数据(如读 写 删)。
* V9 t2 K" i, {( c1 @6 k我爱电脑技术社区--打造最好的电脑技术自学交流平台
+ Z$ O+ T! n3 d- U' [我爱电脑技术社区--打造最好的电脑技术自学交流平台// 取出用户和被访问对象之间的权限关系,这种权限关系可能不只一个,也就是说,用户
1 g& x/ p& J& g4 c* {/ l. q: B我爱电脑技术论坛* c* I. N7 s4 ]9 l; d" P- m" P" D3 A9 R
//可能对被访问对象拥有读 写 删等多个权限,将其打包在Hasbtable中。
* j) f' ?; D! [- ?& I2 H我爱电脑技术社区--打造最好的电脑技术自学交流平台
# T6 K; E$ l5 G* J: \- R8 X3 ]我爱电脑技术论坛Hashtable features = loadFeaturesForUser(sApplicationName, sUserID); www.520diannao.com  e) S/ z* x% `0 N% x
我爱电脑技术社区--打造最好的电脑技术自学交流平台- M& d5 v% U( F; [( R
3. 创建一个用户对象
4 k5 n0 D4 z  \! Z& B9 j! h打造最好的电脑自学交流论坛
3 f3 b) p* b  @) W; Z/ Z9 d我爱电脑技术论坛User user = new UserImpl(sUserID, new Hashtable() );
- \. s) J0 W$ z0 E+ }3 L$ t
2 Q6 Y* j* X, D电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站4. 为这个用户创建一个活动的acl entry
/ }( @' B8 |( V5 N; z' v我爱电脑技术论坛& T5 W; E" V* P6 N
addAclEntry( user, features); 我爱电脑技术社区--打造最好的电脑技术自学交流平台: k6 d  o0 Z0 I! L: ^

1 N0 q( }" w* n( s% p其中最关键的是第四步addAclEntry,我们看看其如何实现的:
# j6 ]8 F3 l! K9 ?5 F  @" h我爱电脑技术论坛
6 A5 J3 y; A! Y$ J! Z5 R0 z电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站// 为这个用户创建一个新的Acl entry
1 I+ ?; \6 V- S' B5 W: l我爱电脑技术社区--打造最好的电脑技术自学交流平台
: o9 I) q0 W( ^2 }4 O我爱电脑技术论坛AclEntry newAclEntry = new AclEntryImpl( user);
; l+ p' ^$ S& S) o( K: \* A3 Z& A4 s: s6 h; h0 J, j
//遍历Hashtable features,将其中多种权限加入:
  J7 G1 a$ f# n8 O% Z$ J( e: s9 C/ L我爱电脑技术论坛
) K3 A% w3 j0 l2 ^# \: J. K" g打造最好的电脑自学交流论坛.... 打造最好的电脑自学交流论坛- x8 a4 G* a) A1 _

9 p! J1 Y; c" Y( ?feature = (Feature) hFeatures.get(keyName); / p7 A. z, f' p' k

. B% d/ `0 f/ \4 a- E2 _0 dwww.520diannao.comnewAclEntry.addPermission( feature );
) p) B/ J6 u' @# w3 I5 {我爱电脑技术论坛
3 C+ w: O4 `- N1 c.... www.520diannao.com( t$ T! w- v! u$ i

0 j: s# x7 c8 h电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站最后也要加入主体拥有者SecurityOwner 我爱电脑技术论坛2 ?$ L. u1 U( v
) H3 S3 t4 [5 a' i% Y
这样一个安全体系就已经建立完成。 ! d+ V9 ]5 O! e) \) V+ E+ J

: v' ?' z) R3 L5 T
5 `2 ^! {+ `4 [% o打造最好的电脑自学交流论坛当你在系统中要检验某个用户使用拥有某个权限,如读的权利时,只要acl.checkPermission(user, feature )就可以,acl是ACL的一个实例,这样权限检查就交给java.security.acl.ACL 去处理了。
* a$ m3 h( U3 E1 W+ @; b电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
% O( V7 ^- {5 D3 y0 t我爱电脑技术论坛
6 y6 @7 [/ b' t  k有了ACL机制后,我们就可以在我们系统中使用动态Proxy模式来对具体对象或方法进行控制,比如,我们有一个Report类,有些用户可以读,有些用户可以写(哪些用户可以读 哪些用户可以写,已经在上面ACL里部署完成)。
% X% l" R! I! l6 F2 V我爱电脑技术社区--打造最好的电脑技术自学交流平台
) M: u' s/ k4 X. |; j我爱电脑技术社区--打造最好的电脑技术自学交流平台
2 ^/ z& e9 x1 K& V我爱电脑技术论坛从Java 1.3开始, Sun提供了Dynamic Proxy API.为了使动态Proxy能够工作,第一你必须有一个Proxy接口,还要有一个继承InvocationHandler的Proxy类。
9 J4 J& t& E! j$ e' `打造最好的电脑自学交流论坛
# D) @% E. f; K3 Z' ?我爱电脑技术社区--打造最好的电脑技术自学交流平台在下面的例子中,我们设定有三种用户:普通人;雇员;经理.权限是这样:普通人可以读报告;雇员和经理可以修改报告。

TOP

按通常思维,我们对于读权限,我们设计一个具备读的角色类: 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站2 |& S; m$ n& i# q
www.520diannao.com4 i& j1 E% H# p. E5 Q. \
public interface IpersonRO {
* P/ c& K: `0 f电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
6 T! @9 m( i5 X5 l! o) l我爱电脑技术社区--打造最好的电脑技术自学交流平台public String getName(); 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站. f# a8 c; K' y" r' ^& `1 t

* l+ H% O7 K5 i& a打造最好的电脑自学交流论坛public String getAddress();
0 T' C$ ~, c, i. K
' ^, A% ]: F/ X, N( H电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站public String getPhoneNumber(); 我爱电脑技术社区--打造最好的电脑技术自学交流平台# g/ b8 C$ Y2 n6 Z1 L' y  R8 d( D+ E

! v- Q0 y, D7 H7 S5 U  A$ M}
4 L9 o  }, w# B5 ~2 T打造最好的电脑自学交流论坛
4 [  }7 b" e$ B4 |5 ~- k( n& K3 D) U我爱电脑技术社区--打造最好的电脑技术自学交流平台
: f5 ^6 ]/ @+ a. u/ P我爱电脑技术论坛类里面都是读的方法,这是一种粗粒度访问控制,也就是说把读写权限只落实到类(对象)上,这样的话,我们还要为写的角色再建一个类,很显然这不是一个很好的方法,使用动态proxy+acl就可以实现很好的细粒度控制。 www.520diannao.com$ V; V% q0 E1 d3 }
打造最好的电脑自学交流论坛, D: G$ H! E- |6 }& f4 U# G
public class ReportProxy implements InvocationHandler
5 O2 B# B3 k- d: K; }$ p5 e& u! _我爱电脑技术社区--打造最好的电脑技术自学交流平台6 k- }4 P9 V% U4 v+ o* J( _0 h/ S: ^
{
, y3 K) v, ]/ }* t; Zwww.520diannao.comwww.520diannao.com  p" N( I, D! S7 U0 d
private Map map;
3 I) E6 b" K" j  |" W+ t8 y2 \- K打造最好的电脑自学交流论坛
) |& s+ N/ w5 nwww.520diannao.compublic static Object newInstance(Map map,Class[] interfaces) 我爱电脑技术社区--打造最好的电脑技术自学交流平台2 S/ C( I+ c. Z

* y8 |  F* R4 f: l1 c6 T& Q; Q# u7 ?0 L打造最好的电脑自学交流论坛{ 打造最好的电脑自学交流论坛0 O& h" c( f- @# d5 d% r( j4 i$ n  B

* t# e5 Y5 R: m1 `8 Dwww.520diannao.comreturn Proxy.newProxyInstance(map.getClass().getClassLoader(), interfaces,new ReportProxy(map));
7 }; Z1 L$ Q: k& S0 u0 k3 O( F1 b我爱电脑技术论坛我爱电脑技术论坛# [" C* ^( C" `
} 打造最好的电脑自学交流论坛7 A" j/ v$ H3 V/ \) I& `
我爱电脑技术论坛4 a" k0 d* \9 s& l6 W9 X
public ReportProxy(Map map) 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站3 i8 @$ z* @( Q, r6 s7 T1 F+ h

0 Y1 C; J1 [, ?* p0 b, f( e, P" r打造最好的电脑自学交流论坛{ 我爱电脑技术论坛  U' Z. u5 q" H7 g" B  \

# X: R3 s9 ]0 k# [8 R+ E打造最好的电脑自学交流论坛this.map = map; 打造最好的电脑自学交流论坛4 D9 D+ n" r$ o; a

7 O, J% M: g8 m) ]1 ~+ W( ?! M( s% B打造最好的电脑自学交流论坛}
* F. B  ?( s, Z+ b5 Q# M  L打造最好的电脑自学交流论坛电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站3 W7 @3 Q, i; |% k; \0 D8 z4 j
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
1 M- c6 c3 o- T5 B# l8 d2 \, ^www.520diannao.com
9 O: P+ W! M! b; j2 C0 y$ `. Lwww.520diannao.com{ 我爱电脑技术论坛7 ]& `, e# h3 K- m; [: `, ]2 T
我爱电脑技术论坛2 k# F4 r: [9 x, B! m
Object result;
. l% q) W  W7 X2 Q, q: ~; w* w) E$ Z
5 c7 F. B; L! U8 i. I( A我爱电脑技术社区--打造最好的电脑技术自学交流平台String methodName = m.getName(); 打造最好的电脑自学交流论坛: I2 g% ~' C- |2 W: \
我爱电脑技术社区--打造最好的电脑技术自学交流平台( u. ^1 k1 U* {2 Z# ^- Q6 X, L
if (methodName.startsWith("get"))
: F2 N" h! p3 I- A$ ^8 ~9 W电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
0 m' u# S0 k" rwww.520diannao.com{ $ O5 O( P9 F; V
打造最好的电脑自学交流论坛, U! b# Y$ m2 f9 I  k- \! b
if (!acl.checkPermission(user, "read")) return null;
! b  l2 \+ P# i: x% B打造最好的电脑自学交流论坛www.520diannao.com* ]) z# e" i! |: ~7 Z8 ~  u# T
String name = methodName.substring(
# {& S5 e8 V9 A& N: ^" i- B( h我爱电脑技术论坛
/ C/ W6 i# E; D% i5 [! Q7 }电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站methodName.indexOf("get")+3); 6 v! `# S) c* l8 U

3 F3 [# ]: p8 g8 N- v( ^www.520diannao.comreturn map.get(name); www.520diannao.com% ?' A& L. Z2 |- a! L: d: _
电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站) c: J- _7 p4 \* I& H
}
: Z) i1 K* F: m0 Y* o) l; x
: H! ^5 _/ q6 t0 ~& _1 g. @2 \else if (methodName.startsWith("set"))
0 G+ V' o' s% @# r0 F0 N  o$ D* Lwww.520diannao.com
" h* s. S/ c5 _5 Y& D# W9 F; v打造最好的电脑自学交流论坛{ 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站8 _" f' p8 I. [: @. Q

% W* R6 s) Y3 }  z* X5 q. e: jwww.520diannao.comif (!acl.checkPermission(user, "write")) return null; 打造最好的电脑自学交流论坛. f- \- e( `# W# r: V6 N) W
我爱电脑技术社区--打造最好的电脑技术自学交流平台0 a. p. t1 [" ^. Z- e# b
String name = methodName.substring( 1 ]/ t( K1 Z0 T/ S* s

" Q1 D; u8 r4 _www.520diannao.commethodName.indexOf("set")+3); 我爱电脑技术论坛  W& R4 H& w; H5 k7 u

- I$ M6 a5 ^" Ewww.520diannao.commap.put(name, args[0]);   s( ^* O- l% v( Z

; `! k# x' j  C% d6 ^1 a我爱电脑技术论坛return null; 我爱电脑技术论坛, S/ ]( D" d, s: F% \5 g) K% G2 d& @

1 e3 n8 z4 B7 X: A! L5 H# R1 ~打造最好的电脑自学交流论坛}
; ?5 ]- L4 R2 n, s* y打造最好的电脑自学交流论坛4 {0 a7 X4 H9 q' b: v
else if (methodName.startsWith("is"))
* Q: u9 J3 E% E& m; i$ d/ U2 J
- L2 t1 g0 _) Z9 }* p( B. u2 u; X( G{ $ x- D* {  R3 n" S$ X2 G5 `/ o
电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站7 u  ~' s* y7 p' V* }# c
if (!acl.checkPermission(user, "read")) return null;
" t' C  i$ {' ^6 r7 @9 {www.520diannao.com
! C/ m6 r# U* C6 _4 Twww.520diannao.comString name = methodName.substring(
$ A! ?- a5 o1 b  [5 O. x3 F打造最好的电脑自学交流论坛
' n5 M, z: ]1 b: W5 S2 P打造最好的电脑自学交流论坛methodName.indexOf("is")+2);
2 A/ W  x, s( {6 S: P6 B% Q* v
- |! m3 B# y1 M$ O电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站return(map.get(name));
- V, @% Y7 F  `1 X  h, y4 u  ywww.520diannao.com电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站6 K: I% D! @# I5 M5 Y3 u; K% E+ k0 B" A
}
8 J  {9 f- G. V/ s( jwww.520diannao.com
& D* T. {( |1 \" ~( pwww.520diannao.comreturn null; 我爱电脑技术社区--打造最好的电脑技术自学交流平台) j/ @$ [% R- l2 y
电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站  Z: I3 A5 J8 V( K
}
% Y& P, c  B. V/ J$ ^. w8 h/ f; Cwww.520diannao.com打造最好的电脑自学交流论坛  I" A; _9 }. P: o# |3 c% w  w
}

TOP

发新话题