Acegi+hibernate 动态实现基于角色的权限管理
可以看到它是通过读配置文件来判断执行某个方法所需要的角色的,再看这几句
<
bean
id
="filterInvocationInterceptor"
class
="org.acegisecurity.intercept.web.FilterSecurityInterceptor"
>
< property name ="authenticationManager" >< ref bean ="authenticationManager" /></ property >
< property name ="accessDecisionManager" >< ref local ="httpRequestAccessDecisionManager" /></ property >
< property name ="objectDefinitionSource" >
< value >
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/index.jsp=ROLE_ANONYMOUS,ROLE_USER
/hello.htm=ROLE_ANONYMOUS,ROLE_USER
/logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
/switchuser.jsp=ROLE_SUPERVISOR
/j_acegi_switch_user=ROLE_SUPERVISOR
/acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
/**=ROLE_USER
</ value >
</ property >
</ bean >
同样是将页面的访问权限写死在配置文件中,再来看看它的tag是如何处理的
< property name ="authenticationManager" >< ref bean ="authenticationManager" /></ property >
< property name ="accessDecisionManager" >< ref local ="httpRequestAccessDecisionManager" /></ property >
< property name ="objectDefinitionSource" >
< value >
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/index.jsp=ROLE_ANONYMOUS,ROLE_USER
/hello.htm=ROLE_ANONYMOUS,ROLE_USER
/logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
/switchuser.jsp=ROLE_SUPERVISOR
/j_acegi_switch_user=ROLE_SUPERVISOR
/acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
/**=ROLE_USER
</ value >
</ property >
</ bean >
<
auth:authorize
ifAnyGranted
="ROLE_DELETE"
>
< a href ="" > 删除 </ a >
</ auth:authorize >
可见它是要求我们对链接或者其他资源的保护时提供 用户角色,可是既然角色是用户自己添加的我们又如何来写死在这里呢?
< a href ="" > 删除 </ a >
</ auth:authorize >
还有就是它对用户验证默认使用的是jdbc,即 JdbcDaoImpl
<
bean
id
="transactionManager"
class
="org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
< property name ="dataSource" >< ref local ="dataSource" /></ property >
</ bean >
而我们希望基于Hibernate的Dao来实现。
< property name ="dataSource" >< ref local ="dataSource" /></ property >
</ bean >
可见仅仅使用现有的acegi 是 无法满足我们项目开发的需求的。
解决方法:
1: 开发基于数据库的保护资源。
看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类
public
abstract
class
AbstractMethodDefinitionSource
implements MethodDefinitionSource {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class);
//~ Methods ================================================================
public ConfigAttributeDefinition getAttributes(Object object)
throws IllegalArgumentException {
Assert.notNull(object, "Object cannot be null");
if (object instanceof MethodInvocation) {
return this.lookupAttributes(((MethodInvocation) object).getMethod());
}
if (object instanceof JoinPoint) {
JoinPoint jp = (JoinPoint) object;
Class targetClazz = jp.getTarget().getClass();
String targetMethodName = jp.getStaticPart().getSignature().getName();
Class[] types = ((CodeSignature) jp.getStaticPart().getSignature())
.getParameterTypes();
if (logger.isDebugEnabled()) {
logger.debug("Target Class: " + targetClazz);
logger.debug("Target Method Name: " + targetMethodName);
for (int i = 0; i < types.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Target Method Arg #" + i + ": "
+ types[i]);
}
}
}
try {
return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types));
} catch (NoSuchMethodException nsme) {
throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp);
}
}
throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint");
}
public boolean supports(Class clazz) {
return (MethodInvocation.class.isAssignableFrom(clazz)
|| JoinPoint.class.isAssignableFrom(clazz));
}
protected abstract ConfigAttributeDefinition lookupAttributes(Method method);
}
implements MethodDefinitionSource {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class);
//~ Methods ================================================================
public ConfigAttributeDefinition getAttributes(Object object)
throws IllegalArgumentException {
Assert.notNull(object, "Object cannot be null");
if (object instanceof MethodInvocation) {
return this.lookupAttributes(((MethodInvocation) object).getMethod());
}
if (object instanceof JoinPoint) {
JoinPoint jp = (JoinPoint) object;
Class targetClazz = jp.getTarget().getClass();
String targetMethodName = jp.getStaticPart().getSignature().getName();
Class[] types = ((CodeSignature) jp.getStaticPart().getSignature())
.getParameterTypes();
if (logger.isDebugEnabled()) {
logger.debug("Target Class: " + targetClazz);
logger.debug("Target Method Name: " + targetMethodName);
for (int i = 0; i < types.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Target Method Arg #" + i + ": "
+ types[i]);
}
}
}
try {
return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types));
} catch (NoSuchMethodException nsme) {
throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp);
}
}
throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint");
}
public boolean supports(Class clazz) {
return (MethodInvocation.class.isAssignableFrom(clazz)
|| JoinPoint.class.isAssignableFrom(clazz));
}
protected abstract ConfigAttributeDefinition lookupAttributes(Method method);
}
我们要做的就是实现它的
protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法,
以下是我的实现方法,大致思路是这样,通过由抽象类传来的Method 对象得到
调用这个方法的 包名,类名,方法名 也就是secureObjectName, 查询数据库并将结果映射为Function 也就是secureObject ,由于Function 与 Role 的多对多关系 可以得到 Function所对应的 Roles ,在将role 包装成GrantedAuthority (也就是acegi中的角色)。其中由于频繁的对数据库的查询 所以使用Ehcache 来作为缓存。
1
package
sample.auth;
2
3 import java.lang.reflect.Method;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.Collection;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Set;
10
11 import org.acegisecurity.ConfigAttributeDefinition;
12 import org.acegisecurity.ConfigAttributeEditor;
13 import org.acegisecurity.GrantedAuthority;
14 import org.acegisecurity.GrantedAuthorityImpl;
15 import org.acegisecurity.intercept.method.AbstractMethodDefinitionSource;
16 import org.springframework.util.Assert;
17
18 import sample.auth.cache.AuthorityBasedFunctionCache;
19 import sample.auth.cache.info.FunctionByNameCache;
20 import sample.dao.IBaseDao;
21 import sample.mappings.function.Function;
22 import sample.mappings.role.Role;
23
24 public class DatabaseDrivenMethodDefinitionSourcew extends
25 AbstractMethodDefinitionSource {
26
27 // baseDao 提供通过HIbenate对数据库操作的实现
28 private IBaseDao baseDao;
29 // AuthorityBasedFunctionCache 通过Function 查 Role 时缓存
30 private AuthorityBasedFunctionCache cache;
31 // FunctionByNameCache 由反射到的方法名查找 数据库对应的Function 时的缓存
32 private FunctionByNameCache functionCache;
33
34 public FunctionByNameCache getFunctionCache() {
35 return functionCache;
36 }
37
38 public void setFunctionCache(FunctionByNameCache functionCache) {
39 this .functionCache = functionCache;
40 }
41
42 protected ConfigAttributeDefinition lookupAttributes(Method mi) {
43
44 Assert.notNull(mi, " lookupAttrubutes in the DatabaseDrivenMethodDefinitionSourcew is null " );
45 String secureObjectName = mi.getDeclaringClass().getName() + " . " + mi.getName();
46 // Function 为数据库中保护资源的映射
47 Function secureObject = functionCache.getFunctionByCache(secureObjectName);
48
49 if (secureObject == null ) // if secure object not exist in database
50 {
51 secureObject = (Function)baseDao.loadByKey(Function. class , " protectfunction " , secureObjectName);
52 functionCache.putFunctionInCache(secureObject);
53 }
54
55 if (secureObject == null )
56 Assert.notNull(secureObject, " secureObject(Function) not found in db " );
57 // retrieving roles associated with this secure object
58
59 Collection roles = null ;
60 GrantedAuthority[] grantedAuthoritys = cache.getAuthorityFromCache(secureObject.getName());
61 // 如果是第一次 cache 为空
62 if (grantedAuthoritys == null ){
63
64 Set rolesSet = secureObject.getRoles();
65 Iterator it = rolesSet.iterator();
66 List list = new ArrayList();
67 while (it.hasNext()){
68
69 Role role = (Role)it.next();
70 GrantedAuthority g = new GrantedAuthorityImpl(role.getName());
71 list.add(g);
72 }
73 grantedAuthoritys = (GrantedAuthority[])list.toArray( new GrantedAuthority[ 0 ]);
74 cache.putAuthorityInCache(secureObject.getName(),grantedAuthoritys);
75 roles = Arrays.asList(grantedAuthoritys);
76 } else {
77
78 roles = Arrays.asList(grantedAuthoritys);
79 }
80
81 if ( ! roles.isEmpty()){
82 ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
83 StringBuffer rolesStr = new StringBuffer();
84 for (Iterator it = roles.iterator();it.hasNext();){
85 GrantedAuthority role = (GrantedAuthority)it.next();
86 rolesStr.append(role.getAuthority()).append( " , " );
87 }
88
89 configAttrEditor.setAsText( rolesStr.toString().substring( 0 ,rolesStr.length() - 1 ) );
90 ConfigAttributeDefinition configAttrDef = (ConfigAttributeDefinition)configAttrEditor.getValue();
91 return configAttrDef;
92 }
93
94 Assert.notEmpty(roles, " collection of roles is null or empty " );
95 return null ;
96
97
98 }
99
100 public Iterator getConfigAttributeDefinitions() {
101
102 return null ;
103 }
104
105
106 public IBaseDao getBaseDao() {
107 return baseDao;
108 }
109
110
111 public void setBaseDao(IBaseDao baseDao) {
112 this .baseDao = baseDao;
113 }
114
115 public AuthorityBasedFunctionCache getCache() {
116 return cache;
117 }
118
119 public void setCache(AuthorityBasedFunctionCache cache) {
120 this .cache = cache;
121 }
122
123 }
124
2
3 import java.lang.reflect.Method;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.Collection;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Set;
10
11 import org.acegisecurity.ConfigAttributeDefinition;
12 import org.acegisecurity.ConfigAttributeEditor;
13 import org.acegisecurity.GrantedAuthority;
14 import org.acegisecurity.GrantedAuthorityImpl;
15 import org.acegisecurity.intercept.method.AbstractMethodDefinitionSource;
16 import org.springframework.util.Assert;
17
18 import sample.auth.cache.AuthorityBasedFunctionCache;
19 import sample.auth.cache.info.FunctionByNameCache;
20 import sample.dao.IBaseDao;
21 import sample.mappings.function.Function;
22 import sample.mappings.role.Role;
23
24 public class DatabaseDrivenMethodDefinitionSourcew extends
25 AbstractMethodDefinitionSource {
26
27 // baseDao 提供通过HIbenate对数据库操作的实现
28 private IBaseDao baseDao;
29 // AuthorityBasedFunctionCache 通过Function 查 Role 时缓存
30 private AuthorityBasedFunctionCache cache;
31 // FunctionByNameCache 由反射到的方法名查找 数据库对应的Function 时的缓存
32 private FunctionByNameCache functionCache;
33
34 public FunctionByNameCache getFunctionCache() {
35 return functionCache;
36 }
37
38 public void setFunctionCache(FunctionByNameCache functionCache) {
39 this .functionCache = functionCache;
40 }
41
42 protected ConfigAttributeDefinition lookupAttributes(Method mi) {
43
44 Assert.notNull(mi, " lookupAttrubutes in the DatabaseDrivenMethodDefinitionSourcew is null " );
45 String secureObjectName = mi.getDeclaringClass().getName() + " . " + mi.getName();
46 // Function 为数据库中保护资源的映射
47 Function secureObject = functionCache.getFunctionByCache(secureObjectName);
48
49 if (secureObject == null ) // if secure object not exist in database
50 {
51 secureObject = (Function)baseDao.loadByKey(Function. class , " protectfunction " , secureObjectName);
52 functionCache.putFunctionInCache(secureObject);
53 }
54
55 if (secureObject == null )
56 Assert.notNull(secureObject, " secureObject(Function) not found in db " );
57 // retrieving roles associated with this secure object
58
59 Collection roles = null ;
60 GrantedAuthority[] grantedAuthoritys = cache.getAuthorityFromCache(secureObject.getName());
61 // 如果是第一次 cache 为空
62 if (grantedAuthoritys == null ){
63
64 Set rolesSet = secureObject.getRoles();
65 Iterator it = rolesSet.iterator();
66 List list = new ArrayList();
67 while (it.hasNext()){
68
69 Role role = (Role)it.next();
70 GrantedAuthority g = new GrantedAuthorityImpl(role.getName());
71 list.add(g);
72 }
73 grantedAuthoritys = (GrantedAuthority[])list.toArray( new GrantedAuthority[ 0 ]);
74 cache.putAuthorityInCache(secureObject.getName(),grantedAuthoritys);
75 roles = Arrays.asList(grantedAuthoritys);
76 } else {
77
78 roles = Arrays.asList(grantedAuthoritys);
79 }
80
81 if ( ! roles.isEmpty()){
82 ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
83 StringBuffer rolesStr = new StringBuffer();
84 for (Iterator it = roles.iterator();it.hasNext();){
85 GrantedAuthority role = (GrantedAuthority)it.next();
86 rolesStr.append(role.getAuthority()).append( " , " );
87 }
88
89 configAttrEditor.setAsText( rolesStr.toString().substring( 0 ,rolesStr.length() - 1 ) );
90 ConfigAttributeDefinition configAttrDef = (ConfigAttributeDefinition)configAttrEditor.getValue();
91 return configAttrDef;
92 }
93
94 Assert.notEmpty(roles, " collection of roles is null or empty " );
95 return null ;
96
97
98 }
99
100 public Iterator getConfigAttributeDefinitions() {
101
102 return null ;
103 }
104
105
106 public IBaseDao getBaseDao() {
107 return baseDao;
108 }
109
110
111 public void setBaseDao(IBaseDao baseDao) {
112 this .baseDao = baseDao;
113 }
114
115 public AuthorityBasedFunctionCache getCache() {
116 return cache;
117 }
118
119 public void setCache(AuthorityBasedFunctionCache cache) {
120 this .cache = cache;
121 }
122
123 }
124
2:定义 基于方法的 自定义标志
通过以上的分析 , 要想使用acegi 做页面的显示控制仅仅靠角色(Role)是不行的,因为用户可能随时定义出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么办? ,如法炮制。 首先定义出我们自己的GrantedFunction,实现也雷同 GrantedAuthorityImpl
1
package
sample.auth;
2
3 import java.io.Serializable;
4 public class GrantedFunctionImpl implements GrantedFunction , Serializable{
5
6 private String function;
7
8 // ~ Constructors ===========================================================
9
10 public GrantedFunctionImpl(String function) {
11 super ();
12 this .function = function;
13 }
14
15 protected GrantedFunctionImpl() {
16 throw new IllegalArgumentException( " Cannot use default constructor " );
17 }
18
19 // ~ Methods ================================================================
20
21 public String getFunction() {
22 return this .function;
23 }
24
25 public boolean equals(Object obj) {
26 if (obj instanceof String) {
27 return obj.equals( this .function);
28 }
29
30 if (obj instanceof GrantedFunction) {
31 GrantedFunction attr = (GrantedFunction) obj;
32
33 return this .function.equals(attr.getFunction());
34 }
35
36 return false ;
37 }
38
39 public int hashCode() {
40 return this .function.hashCode();
41 }
42
43 public String toString() {
44 return this .function;
45 }
46
47 }
48
2
3 import java.io.Serializable;
4 public class GrantedFunctionImpl implements GrantedFunction , Serializable{
5
6 private String function;
7
8 // ~ Constructors ===========================================================
9
10 public GrantedFunctionImpl(String function) {
11 super ();
12 this .function = function;
13 }
14
15 protected GrantedFunctionImpl() {
16 throw new IllegalArgumentException( " Cannot use default constructor " );
17 }
18
19 // ~ Methods ================================================================
20
21 public String getFunction() {
22 return this .function;
23 }
24
25 public boolean equals(Object obj) {
26 if (obj instanceof String) {
27 return obj.equals( this .function);
28 }
29
30 if (obj instanceof GrantedFunction) {
31 GrantedFunction attr = (GrantedFunction) obj;
32
33 return this .function.equals(attr.getFunction());
34 }
35
36 return false ;
37 }
38
39 public int hashCode() {
40 return this .function.hashCode();
41 }
42
43 public String toString() {
44 return this .function;
45 }
46
47 }
48
以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 FunctionName)查询出对应的Functions,并且包装成grantedFunctions ,然后根据用户的角色查询出用户对应的Functions ,再取这两个集合的交集,最后再根据这个集合是否为空判断是否显示标志体的内容。
1
package
sample.auth;
2 import java.util.Arrays;
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Set;
9
10 import javax.servlet.jsp.JspException;
11 import javax.servlet.jsp.tagext.Tag;
12 import javax.servlet.jsp.tagext.TagSupport;
13
14 import org.acegisecurity.Authentication;
15 import org.acegisecurity.GrantedAuthority;
16 import org.acegisecurity.context.SecurityContextHolder;
17 import org.springframework.util.StringUtils;
18 import org.springframework.web.util.ExpressionEvaluationUtils;
19
20 import sample.web.action.AppContext;
21 /**
22 *
23 * @author limq
24 *
25 */
26 public class AuthorizeActionTag extends TagSupport{
27
28 private String ifAllGranted = "" ;
29 private String ifAnyGranted = "" ;
30 private String ifNotGranted = "" ;
31
32 public void setIfAllGranted(String ifAllGranted) throws JspException {
33 this .ifAllGranted = ifAllGranted;
34 }
35
36 public String getIfAllGranted() {
37 return ifAllGranted;
38 }
39
40 public void setIfAnyGranted(String ifAnyGranted) throws JspException {
41 this .ifAnyGranted = ifAnyGranted;
42 }
43
44 public String getIfAnyGranted() {
45 return ifAnyGranted;
46 }
47
48 public void setIfNotGranted(String ifNotGranted) throws JspException {
49 this .ifNotGranted = ifNotGranted;
50 }
51
52 public String getIfNotGranted() {
53 return ifNotGranted;
54 }
55
56 public int doStartTag() throws JspException {
57 if ((( null == ifAllGranted) || "" .equals(ifAllGranted))
58 && (( null == ifAnyGranted) || "" .equals(ifAnyGranted))
59 && (( null == ifNotGranted) || "" .equals(ifNotGranted))) {
60 return Tag.SKIP_BODY;
61 }
62
63 final Collection granted = getPrincipalFunctionByAuthorities();
64
65 final String evaledIfNotGranted = ExpressionEvaluationUtils
66 .evaluateString( " ifNotGranted " , ifNotGranted, pageContext);
67
68 if (( null != evaledIfNotGranted) && ! "" .equals(evaledIfNotGranted)) {
69 Set grantedCopy = retainAll(granted,
70 parseSecurityString(evaledIfNotGranted));
71
72 if ( ! grantedCopy.isEmpty()) {
73 return Tag.SKIP_BODY;
74 }
75 }
76
77 final String evaledIfAllGranted = ExpressionEvaluationUtils
78 .evaluateString( " ifAllGranted " , ifAllGranted, pageContext);
79
80 if (( null != evaledIfAllGranted) && ! "" .equals(evaledIfAllGranted)) {
81 if ( ! granted.containsAll(parseSecurityString(evaledIfAllGranted))) {
82 return Tag.SKIP_BODY;
83 }
84 }
85
86 final String evaledIfAnyGranted = ExpressionEvaluationUtils
87 .evaluateString( " ifAnyGranted " , ifAnyGranted, pageContext);
88
89 if (( null != evaledIfAnyGranted) && ! "" .equals(evaledIfAnyGranted)) {
90 Set grantedCopy = retainAll(granted,
91 parseSecurityString(evaledIfAnyGranted));
92
93 if (grantedCopy.isEmpty()) {
94 return Tag.SKIP_BODY;
95 }
96 }
97
98 return Tag.EVAL_BODY_INCLUDE;
99 }
100 /**
101 * 得到用户的Authentication,并且从Authentication中获得 Authorities,进而得到 授予用户的 Function
102 * @return
103 */
104 private Collection getPrincipalFunctionByAuthorities() {
105
106
107 Authentication currentUser = SecurityContextHolder.getContext()
108 .getAuthentication();
109 if ( null == currentUser) {
110 return Collections.EMPTY_LIST;
111 }
112
113 if (( null == currentUser.getAuthorities())
114 || (currentUser.getAuthorities().length < 1 )) {
115 return Collections.EMPTY_LIST;
116 }
117 // currentUser.getAuthorities() 返回的是 GrantedAuthority[]
118 List granted = Arrays.asList(currentUser.getAuthorities());
119 AuthDao authDao = (AuthDao) AppContext.getInstance().getAppContext().getBean( " authDao " );
120 Collection grantedFunctions = authDao.getFunctionsByRoles(granted);
121 return grantedFunctions;
122 }
123
124 /**
125 * 得到用户功能(Function)的集合,并且验证是否合法
126 * @param c Collection 类型
127 * @return Set类型
128 */
129 private Set SecurityObjectToFunctions(Collection c) {
130 Set target = new HashSet();
131
132 for (Iterator iterator = c.iterator(); iterator.hasNext();) {
133 GrantedFunction function = (GrantedFunction) iterator.next();
134
135 if ( null == function.getFunction()) {
136 throw new IllegalArgumentException(
137 " Cannot process GrantedFunction objects which return null from getFunction() - attempting to process "
138 + function.toString());
139 }
140
141 target.add(function.getFunction());
142 }
143
144 return target;
145 }
146
147 /**
148 * 处理页面标志属性 ,用' ,'区分
149 */
150 private Set parseSecurityString(String functionsString) {
151 final Set requiredFunctions = new HashSet();
152 final String[] functions = StringUtils
153 .commaDelimitedListToStringArray(functionsString);
154
155 for ( int i = 0 ; i < functions.length; i ++ ) {
156 String authority = functions[i];
157
158 // Remove the role's whitespace characters without depending on JDK 1.4+
159 // Includes space, tab, new line, carriage return and form feed.
160 String function = StringUtils.replace(authority, " " , "" );
161 function = StringUtils.replace(function, " /t " , "" );
162 function = StringUtils.replace(function, " /r " , "" );
163 function = StringUtils.replace(function, " /n " , "" );
164 function = StringUtils.replace(function, " /f " , "" );
165
166 requiredFunctions.add( new GrantedFunctionImpl(function));
167 }
168
169 return requiredFunctions;
170 }
171 /**
172 * 获得用户所拥有的Function 和 要求的 Function 的交集
173 * @param granted 用户已经获得的Function
174 * @param required 所需要的Function
175 * @return
176 */
177
178 private Set retainAll( final Collection granted, final Set required) {
179 Set grantedFunction = SecurityObjectToFunctions(granted);
180 Set requiredFunction = SecurityObjectToFunctions(required);
181 // retailAll() 获得 grantedFunction 和 requiredFunction 的交集
182 // 即删除 grantedFunction 中 除了 requiredFunction 的项
183 grantedFunction.retainAll(requiredFunction);
184
185 return rolesToAuthorities(grantedFunction, granted);
186 }
187
188 /**
189 *
190 * @param grantedFunctions 已经被过滤过的Function
191 * @param granted 未被过滤过的,即用户所拥有的Function
192 * @return
193 */
194 private Set rolesToAuthorities(Set grantedFunctions, Collection granted) {
195 Set target = new HashSet();
196
197 for (Iterator iterator = grantedFunctions.iterator(); iterator.hasNext();) {
198 String function = (String) iterator.next();
199
200 for (Iterator grantedIterator = granted.iterator();
201 grantedIterator.hasNext();) {
202 GrantedFunction grantedFunction = (GrantedFunction) grantedIterator
203 .next();
204
205 if (grantedFunction.getFunction().equals(function)) {
206 target.add(grantedFunction);
207
208 break ;
209 }
210 }
211 }
212
213 return target;
214 }
215 }
216
217
再说明一下吧,通过 AppContext 获得了Spring的上下文,以及AuthDao(实际意义上讲以不再是单纯的Dao,应该是Service)
2 import java.util.Arrays;
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Set;
9
10 import javax.servlet.jsp.JspException;
11 import javax.servlet.jsp.tagext.Tag;
12 import javax.servlet.jsp.tagext.TagSupport;
13
14 import org.acegisecurity.Authentication;
15 import org.acegisecurity.GrantedAuthority;
16 import org.acegisecurity.context.SecurityContextHolder;
17 import org.springframework.util.StringUtils;
18 import org.springframework.web.util.ExpressionEvaluationUtils;
19
20 import sample.web.action.AppContext;
21 /**
22 *
23 * @author limq
24 *
25 */
26 public class AuthorizeActionTag extends TagSupport{
27
28 private String ifAllGranted = "" ;
29 private String ifAnyGranted = "" ;
30 private String ifNotGranted = "" ;
31
32 public void setIfAllGranted(String ifAllGranted) throws JspException {
33 this .ifAllGranted = ifAllGranted;
34 }
35
36 public String getIfAllGranted() {
37 return ifAllGranted;
38 }
39
40 public void setIfAnyGranted(String ifAnyGranted) throws JspException {
41 this .ifAnyGranted = ifAnyGranted;
42 }
43
44 public String getIfAnyGranted() {
45 return ifAnyGranted;
46 }
47
48 public void setIfNotGranted(String ifNotGranted) throws JspException {
49 this .ifNotGranted = ifNotGranted;
50 }
51
52 public String getIfNotGranted() {
53 return ifNotGranted;
54 }
55
56 public int doStartTag() throws JspException {
57 if ((( null == ifAllGranted) || "" .equals(ifAllGranted))
58 && (( null == ifAnyGranted) || "" .equals(ifAnyGranted))
59 && (( null == ifNotGranted) || "" .equals(ifNotGranted))) {
60 return Tag.SKIP_BODY;
61 }
62
63 final Collection granted = getPrincipalFunctionByAuthorities();
64
65 final String evaledIfNotGranted = ExpressionEvaluationUtils
66 .evaluateString( " ifNotGranted " , ifNotGranted, pageContext);
67
68 if (( null != evaledIfNotGranted) && ! "" .equals(evaledIfNotGranted)) {
69 Set grantedCopy = retainAll(granted,
70 parseSecurityString(evaledIfNotGranted));
71
72 if ( ! grantedCopy.isEmpty()) {
73 return Tag.SKIP_BODY;
74 }
75 }
76
77 final String evaledIfAllGranted = ExpressionEvaluationUtils
78 .evaluateString( " ifAllGranted " , ifAllGranted, pageContext);
79
80 if (( null != evaledIfAllGranted) && ! "" .equals(evaledIfAllGranted)) {
81 if ( ! granted.containsAll(parseSecurityString(evaledIfAllGranted))) {
82 return Tag.SKIP_BODY;
83 }
84 }
85
86 final String evaledIfAnyGranted = ExpressionEvaluationUtils
87 .evaluateString( " ifAnyGranted " , ifAnyGranted, pageContext);
88
89 if (( null != evaledIfAnyGranted) && ! "" .equals(evaledIfAnyGranted)) {
90 Set grantedCopy = retainAll(granted,
91 parseSecurityString(evaledIfAnyGranted));
92
93 if (grantedCopy.isEmpty()) {
94 return Tag.SKIP_BODY;
95 }
96 }
97
98 return Tag.EVAL_BODY_INCLUDE;
99 }
100 /**
101 * 得到用户的Authentication,并且从Authentication中获得 Authorities,进而得到 授予用户的 Function
102 * @return
103 */
104 private Collection getPrincipalFunctionByAuthorities() {
105
106
107 Authentication currentUser = SecurityContextHolder.getContext()
108 .getAuthentication();
109 if ( null == currentUser) {
110 return Collections.EMPTY_LIST;
111 }
112
113 if (( null == currentUser.getAuthorities())
114 || (currentUser.getAuthorities().length < 1 )) {
115 return Collections.EMPTY_LIST;
116 }
117 // currentUser.getAuthorities() 返回的是 GrantedAuthority[]
118 List granted = Arrays.asList(currentUser.getAuthorities());
119 AuthDao authDao = (AuthDao) AppContext.getInstance().getAppContext().getBean( " authDao " );
120 Collection grantedFunctions = authDao.getFunctionsByRoles(granted);
121 return grantedFunctions;
122 }
123
124 /**
125 * 得到用户功能(Function)的集合,并且验证是否合法
126 * @param c Collection 类型
127 * @return Set类型
128 */
129 private Set SecurityObjectToFunctions(Collection c) {
130 Set target = new HashSet();
131
132 for (Iterator iterator = c.iterator(); iterator.hasNext();) {
133 GrantedFunction function = (GrantedFunction) iterator.next();
134
135 if ( null == function.getFunction()) {
136 throw new IllegalArgumentException(
137 " Cannot process GrantedFunction objects which return null from getFunction() - attempting to process "
138 + function.toString());
139 }
140
141 target.add(function.getFunction());
142 }
143
144 return target;
145 }
146
147 /**
148 * 处理页面标志属性 ,用' ,'区分
149 */
150 private Set parseSecurityString(String functionsString) {
151 final Set requiredFunctions = new HashSet();
152 final String[] functions = StringUtils
153 .commaDelimitedListToStringArray(functionsString);
154
155 for ( int i = 0 ; i < functions.length; i ++ ) {
156 String authority = functions[i];
157
158 // Remove the role's whitespace characters without depending on JDK 1.4+
159 // Includes space, tab, new line, carriage return and form feed.
160 String function = StringUtils.replace(authority, " " , "" );
161 function = StringUtils.replace(function, " /t " , "" );
162 function = StringUtils.replace(function, " /r " , "" );
163 function = StringUtils.replace(function, " /n " , "" );
164 function = StringUtils.replace(function, " /f " , "" );
165
166 requiredFunctions.add( new GrantedFunctionImpl(function));
167 }
168
169 return requiredFunctions;
170 }
171 /**
172 * 获得用户所拥有的Function 和 要求的 Function 的交集
173 * @param granted 用户已经获得的Function
174 * @param required 所需要的Function
175 * @return
176 */
177
178 private Set retainAll( final Collection granted, final Set required) {
179 Set grantedFunction = SecurityObjectToFunctions(granted);
180 Set requiredFunction = SecurityObjectToFunctions(required);
181 // retailAll() 获得 grantedFunction 和 requiredFunction 的交集
182 // 即删除 grantedFunction 中 除了 requiredFunction 的项
183 grantedFunction.retainAll(requiredFunction);
184
185 return rolesToAuthorities(grantedFunction, granted);
186 }
187
188 /**
189 *
190 * @param grantedFunctions 已经被过滤过的Function
191 * @param granted 未被过滤过的,即用户所拥有的Function
192 * @return
193 */
194 private Set rolesToAuthorities(Set grantedFunctions, Collection granted) {
195 Set target = new HashSet();
196
197 for (Iterator iterator = grantedFunctions.iterator(); iterator.hasNext();) {
198 String function = (String) iterator.next();
199
200 for (Iterator grantedIterator = granted.iterator();
201 grantedIterator.hasNext();) {
202 GrantedFunction grantedFunction = (GrantedFunction) grantedIterator
203 .next();
204
205 if (grantedFunction.getFunction().equals(function)) {
206 target.add(grantedFunction);
207
208 break ;
209 }
210 }
211 }
212
213 return target;
214 }
215 }
216
217
package
sample.auth;
import java.util.Collection;
public interface AuthDao {
/** *//**
* 根据用户的角色集合 得到 用户的 操作权限
* @param granted 已授予用户的角色集合
* @return 操作权限的集合
*/
public Collection getFunctionsByRoles(Collection granted);
}
以下是AuthDao 的实现
import java.util.Collection;
public interface AuthDao {
/** *//**
* 根据用户的角色集合 得到 用户的 操作权限
* @param granted 已授予用户的角色集合
* @return 操作权限的集合
*/
public Collection getFunctionsByRoles(Collection granted);
}
package
sample.auth;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.acegisecurity.GrantedAuthority;
import sample.auth.cache.FunctionCache;
import sample.auth.cache.info.RoleByNameCache;
import sample.dao.IBaseDao;
import sample.mappings.function.Function;
import sample.mappings.role.Role;
public class AuthDaoImpl implements AuthDao {
private IBaseDao baseDao;
private FunctionCache cache;
private RoleByNameCache roleCache;
public RoleByNameCache getRoleCache() {
return roleCache;
}
public void setRoleCache(RoleByNameCache roleCache) {
this .roleCache = roleCache;
}
public FunctionCache getCache() {
return cache;
}
public void setCache(FunctionCache cache) {
this .cache = cache;
}
public IBaseDao getBaseDao() {
return baseDao;
}
public void setBaseDao(IBaseDao baseDao) {
this .baseDao = baseDao;
}
public Collection getFunctionsByRoles(Collection granted) {
Set set = new HashSet();
if ( null == granted) throw new IllegalArgumentException( " Granted Roles cannot be null " );
for (Iterator it = granted.iterator();it.hasNext();){
GrantedAuthority grantedAuthority = (GrantedAuthority)it.next();
Role role = roleCache.getRoleByRoleNameCache(grantedAuthority.getAuthority()); //
if (role == null ){
role = (Role)baseDao.loadByKey(Role. class , " name " , grantedAuthority.getAuthority());
roleCache.putRoleInCache(role);
}
GrantedFunction[] grantedFunctions = cache.getFunctionFromCache(role.getName());
if (grantedFunctions == null ){
Set functions = role.getFunctions();
for (Iterator it2 = functions.iterator();it2.hasNext();){
Function function = (Function)it2.next();
GrantedFunction grantedFunction = new GrantedFunctionImpl(function.getName());
set.add( grantedFunction );
}
grantedFunctions = (GrantedFunction[]) set.toArray( new GrantedFunction[ 0 ]);
cache.putFuncitonInCache(role.getName(),grantedFunctions);
}
for ( int i = 0 ; i < grantedFunctions.length; i ++ ){
GrantedFunction grantedFunction = grantedFunctions[i];
set.add(grantedFunction);
}
}
return set;
}
}
3 基于hibernate的用户验证
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.acegisecurity.GrantedAuthority;
import sample.auth.cache.FunctionCache;
import sample.auth.cache.info.RoleByNameCache;
import sample.dao.IBaseDao;
import sample.mappings.function.Function;
import sample.mappings.role.Role;
public class AuthDaoImpl implements AuthDao {
private IBaseDao baseDao;
private FunctionCache cache;
private RoleByNameCache roleCache;
public RoleByNameCache getRoleCache() {
return roleCache;
}
public void setRoleCache(RoleByNameCache roleCache) {
this .roleCache = roleCache;
}
public FunctionCache getCache() {
return cache;
}
public void setCache(FunctionCache cache) {
this .cache = cache;
}
public IBaseDao getBaseDao() {
return baseDao;
}
public void setBaseDao(IBaseDao baseDao) {
this .baseDao = baseDao;
}
public Collection getFunctionsByRoles(Collection granted) {
Set set = new HashSet();
if ( null == granted) throw new IllegalArgumentException( " Granted Roles cannot be null " );
for (Iterator it = granted.iterator();it.hasNext();){
GrantedAuthority grantedAuthority = (GrantedAuthority)it.next();
Role role = roleCache.getRoleByRoleNameCache(grantedAuthority.getAuthority()); //
if (role == null ){
role = (Role)baseDao.loadByKey(Role. class , " name " , grantedAuthority.getAuthority());
roleCache.putRoleInCache(role);
}
GrantedFunction[] grantedFunctions = cache.getFunctionFromCache(role.getName());
if (grantedFunctions == null ){
Set functions = role.getFunctions();
for (Iterator it2 = functions.iterator();it2.hasNext();){
Function function = (Function)it2.next();
GrantedFunction grantedFunction = new GrantedFunctionImpl(function.getName());
set.add( grantedFunction );
}
grantedFunctions = (GrantedFunction[]) set.toArray( new GrantedFunction[ 0 ]);
cache.putFuncitonInCache(role.getName(),grantedFunctions);
}
for ( int i = 0 ; i < grantedFunctions.length; i ++ ){
GrantedFunction grantedFunction = grantedFunctions[i];
set.add(grantedFunction);
}
}
return set;
}
}
acegi 默认的 的 用户验证是 通过UserDetailsService 接口 实现的 也就是说我们只要实现了 它的loadUserByUsername 方法。
1
2 public UserDetails loadUserByUsername(String username)
3 throws UsernameNotFoundException, DataAccessException;
以下是我的实现
2 public UserDetails loadUserByUsername(String username)
3 throws UsernameNotFoundException, DataAccessException;
1
package
sample.auth;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.Set;
7
8 import org.acegisecurity.GrantedAuthority;
9 import org.acegisecurity.GrantedAuthorityImpl;
10 import org.acegisecurity.userdetails.User;
11 import org.acegisecurity.userdetails.UserDetails;
12 import org.acegisecurity.userdetails.UserDetailsService;
13 import org.acegisecurity.userdetails.UsernameNotFoundException;
14 import org.springframework.dao.DataAccessException;
15
16 import sample.auth.cache.AuthorityBasedUserCache;
17 import sample.dao.IBaseDao;
18 import sample.mappings.role.Role;
19 import sample.utils.MisUtils;
20
21 public class HibernateDaoImpl implements UserDetailsService{
22
23
24 private String rolePrefix = "" ;
25 private boolean usernameBasedPrimaryKey = false ;
26 private AuthorityBasedUserCache cache;
27
28 private IBaseDao baseDao;
29
30 public String getRolePrefix() {
31 return rolePrefix;
32 }
33
34 public void setRolePrefix(String rolePrefix) {
35 this .rolePrefix = rolePrefix;
36 }
37
38 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
39 UserDetails user = getUsersByUsernameQuery(username);
40 if (user == null ) return null ;
41
42 GrantedAuthority[] arrayAuths = getAuthoritiesByUsernameQuery(username);
43 if (arrayAuths.length == 0 ) {
44 throw new UsernameNotFoundException( " User has no GrantedAuthority " );
45 }
46
47 return new User(username, user.getPassword(), user.isEnabled(),
48 true , true , true , arrayAuths);
49 }
50
51 /**
52 * 根据用户名查找用户
53 * @param username
54 * @return
55 * @throws DataAccessException
56 */
57 public UserDetails getUsersByUsernameQuery(String username) throws DataAccessException {
58 sample.mappings.user.User misUser = (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username);
59 if (misUser != null )
60 {
61 org.acegisecurity.userdetails.UserDetails user =
62 new User(misUser.getName(),misUser.getPassword(),MisUtils.parseBoolean(misUser.getEnable()), true , true , true ,getAuthoritiesByUsernameQuery(username));
63 return user;
64 } else
65 return null ;
66 }
67
68 /**
69 * 根据用户名查找角色
70 * @param username
71 * @return GrantedAuthority[] 用户角色
72 * @throws DataAccessException
73 */
74 public GrantedAuthority[] getAuthoritiesByUsernameQuery(String username)
75 throws DataAccessException {
76 sample.mappings.user.User misUser
77 = (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username);
78
79 if (misUser != null ){
80 GrantedAuthority[] grantedAuthoritys = cache.getAuthorityFromCache(misUser.getName());
81
82 if (grantedAuthoritys == null ){
83
84 Set roles = misUser.getRoles();
85 Iterator it = roles.iterator();
86
87 List list = new ArrayList();
88 while (it.hasNext() ){
89
90 GrantedAuthorityImpl gai = new GrantedAuthorityImpl( ((Role)it.next()).getName() );
91 list.add(gai);
92 }
93 grantedAuthoritys = (GrantedAuthority[]) list.toArray( new GrantedAuthority[ 0 ]);
94 cache.putAuthorityInCache(misUser.getName(),grantedAuthoritys);
95 return grantedAuthoritys;
96
97 }
98 return grantedAuthoritys;
99 }
100
101 return null ;
102 }
103
104 public IBaseDao getBaseDao() {
105 return baseDao;
106 }
107
108 public void setBaseDao(IBaseDao baseDao) {
109 this .baseDao = baseDao;
110 }
111
112 public AuthorityBasedUserCache getCache() {
113 return cache;
114 }
115
116 public void setCache(AuthorityBasedUserCache cache) {
117 this .cache = cache;
118 }
119
120 }
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.Set;
7
8 import org.acegisecurity.GrantedAuthority;
9 import org.acegisecurity.GrantedAuthorityImpl;
10 import org.acegisecurity.userdetails.User;
11 import org.acegisecurity.userdetails.UserDetails;
12 import org.acegisecurity.userdetails.UserDetailsService;
13 import org.acegisecurity.userdetails.UsernameNotFoundException;
14 import org.springframework.dao.DataAccessException;
15
16 import sample.auth.cache.AuthorityBasedUserCache;
17 import sample.dao.IBaseDao;
18 import sample.mappings.role.Role;
19 import sample.utils.MisUtils;
20
21 public class HibernateDaoImpl implements UserDetailsService{
22
23
24 private String rolePrefix = "" ;
25 private boolean usernameBasedPrimaryKey = false ;
26 private AuthorityBasedUserCache cache;
27
28 private IBaseDao baseDao;
29
30 public String getRolePrefix() {
31 return rolePrefix;
32 }
33
34 public void setRolePrefix(String rolePrefix) {
35 this .rolePrefix = rolePrefix;
36 }
37
38 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
39 UserDetails user = getUsersByUsernameQuery(username);
40 if (user == null ) return null ;
41
42 GrantedAuthority[] arrayAuths = getAuthoritiesByUsernameQuery(username);
43 if (arrayAuths.length == 0 ) {
44 throw new UsernameNotFoundException( " User has no GrantedAuthority " );
45 }
46
47 return new User(username, user.getPassword(), user.isEnabled(),
48 true , true , true , arrayAuths);
49 }
50
51 /**
52 * 根据用户名查找用户
53 * @param username
54 * @return
55 * @throws DataAccessException
56 */
57 public UserDetails getUsersByUsernameQuery(String username) throws DataAccessException {
58 sample.mappings.user.User misUser = (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username);
59 if (misUser != null )
60 {
61 org.acegisecurity.userdetails.UserDetails user =
62 new User(misUser.getName(),misUser.getPassword(),MisUtils.parseBoolean(misUser.getEnable()), true , true , true ,getAuthoritiesByUsernameQuery(username));
63 return user;
64 } else
65 return null ;
66 }
67
68 /**
69 * 根据用户名查找角色
70 * @param username
71 * @return GrantedAuthority[] 用户角色
72 * @throws DataAccessException
73 */
74 public GrantedAuthority[] getAuthoritiesByUsernameQuery(String username)
75 throws DataAccessException {
76 sample.mappings.user.User misUser
77 = (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username);
78
79 if (misUser != null ){
80 GrantedAuthority[] grantedAuthoritys = cache.getAuthorityFromCache(misUser.getName());
81
82 if (grantedAuthoritys == null ){
83
84 Set roles = misUser.getRoles();
85 Iterator it = roles.iterator();
86
87 List list = new ArrayList();
88 while (it.hasNext() ){
89
90 GrantedAuthorityImpl gai = new GrantedAuthorityImpl( ((Role)it.next()).getName() );
91 list.add(gai);
92 }
93 grantedAuthoritys = (GrantedAuthority[]) list.toArray( new GrantedAuthority[ 0 ]);
94 cache.putAuthorityInCache(misUser.getName(),grantedAuthoritys);
95 return grantedAuthoritys;
96
97 }
98 return grantedAuthoritys;
99 }
100
101 return null ;
102 }
103
104 public IBaseDao getBaseDao() {
105 return baseDao;
106 }
107
108 public void setBaseDao(IBaseDao baseDao) {
109 this .baseDao = baseDao;
110 }
111
112 public AuthorityBasedUserCache getCache() {
113 return cache;
114 }
115
116 public void setCache(AuthorityBasedUserCache cache) {
117 this .cache = cache;
118 }
119
120 }
最近在做项目遇到了权限管理,用户要求可以自己建立不同的角色对系统的资源进行控制, 不同的用户有不同的角色,又恰恰框架中用到了struts+spring+hibernate,要求在web层调用 业务逻辑层 时不考虑权限,web层可以控制用户的显示界面,逻辑层处理用户权限问题。
想来想去好像只有spring 的aop 可以做到,在调用到 接口 中的方法时,首先检查用户的权限,如果检查通过则继续执行,否则抛出异常。但是新的问题又出现了,如何在逻辑层上来得到当前用户的id,以致用户的 角色,总不能每次都要从web中传来一个 httprequest,或者 session 这类的吧。在网上看了很多资料,发现了acegi,恰好解决了以上的难题,具体的实现原理这里就不多说了,网上有很多相关资料。
说正题,首先来看看acegi 的官方 example ,我下载的是acegi-security-1.0.0-RC1,解压缩后可以看到acegi-security-sample-contacts-filter.war,打开配置文件有这样几句
1
<
bean
id
="contactManagerSecurity"
class
="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"
>
2 < property name ="authenticationManager" >< ref bean ="authenticationManager" /></ property >
3 < property name ="accessDecisionManager" >< ref local ="businessAccessDecisionManager" /></ property >
4 < property name ="afterInvocationManager" >< ref local ="afterInvocationManager" /></ property >
5 < property name ="objectDefinitionSource" >
6 < value >
7 sample.contact.ContactManager.create=ROLE_USER
8 sample.contact.ContactManager.getAllRecipients=ROLE_USER
9 sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ
10 sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ
11 sample.contact.ContactManager.delete=ACL_CONTACT_DELETE
12 sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN
13 sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN
14 </ value >
15 </ property >
16 </ bean >
17
2 < property name ="authenticationManager" >< ref bean ="authenticationManager" /></ property >
3 < property name ="accessDecisionManager" >< ref local ="businessAccessDecisionManager" /></ property >
4 < property name ="afterInvocationManager" >< ref local ="afterInvocationManager" /></ property >
5 < property name ="objectDefinitionSource" >
6 < value >
7 sample.contact.ContactManager.create=ROLE_USER
8 sample.contact.ContactManager.getAllRecipients=ROLE_USER
9 sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ
10 sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ
11 sample.contact.ContactManager.delete=ACL_CONTACT_DELETE
12 sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN
13 sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN
14 </ value >
15 </ property >
16 </ bean >
17