- 浏览: 407010 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (268)
- java (22)
- Acegi (8)
- Ajax (17)
- Annotation (3)
- Ant (3)
- JBOSS (6)
- Xdoclet (1)
- CSS (20)
- Data Warehouse (11)
- DB2 (3)
- DOM (1)
- dos (2)
- JMF (1)
- JMS (5)
- J2EE (17)
- Hibernate (7)
- struts (10)
- CORBA (1)
- 职业 (2)
- JSF (1)
- JSTL (8)
- 其它 (1)
- Log4j (7)
- svg (7)
- quartz (3)
- web2.0 (2)
- velocity (2)
- apache commons (1)
- js (9)
- html (4)
- sql (3)
- linux (4)
- dwr (14)
- spring (5)
- GWT (7)
- portlet (4)
- 软件工程 (10)
- actionscript (1)
- 测试 (1)
- tomcat (3)
- flash (0)
- 线程 (1)
- mysql (6)
- flex (1)
- oracle (7)
- crystalreport (4)
- itext (4)
- memcache (2)
- linux 监控 (2)
- mongodb (1)
- Kafka (5)
- 网络 (2)
- 分布式计算 (2)
最新评论
-
chenyongxin:
mark
JBoss 4.0.2集群基本知识及配置方法指南 -
softor:
我找到了,下载吧:http://ishare.iask.sin ...
jad是最简单的class反编译为java文件的小工具 (转载) -
softor:
求下载
dodo@lovehang.com
jad是最简单的class反编译为java文件的小工具 (转载) -
juedui0769:
不错!
请问: 如何在 将 log4j.appender ...
Tomcat 日志 配置 (转载) -
spp_1987:
// 建立一个上传文件的输出流
...
Struts上传多个及N个文件的例子
学习acegi-security
这几天对acegi研究了一下,现对这几天的研究做个总结。
网上资料对于acegi在web上的应用非常多,所以特意不从web入手,而从一般的java方法入手。
acegi的基本原理就是利用拦截器,对请求进行拦截,在拦截前和拦截后做些安全验证,以达到安全目的。所谓安全,一般包括两个部分,一为认证(authentication),二为授权(authorization)。
1,拦截器体系
acegi中拦截器为分为三类:
(1)filter拦截器(FilterSecurityInterceptor),主要对web应用进行拦截,即利用servlet的filter进行拦截。
(2)method拦截器,分为spring的method拦截器(MethodSecurityInterceptor)和aspectj的method拦截器(AspectJSecurityInterceptor)。
Java代码
public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware,
MessageSourceAware {
private AccessDecisionManager accessDecisionManager;
private AfterInvocationManager afterInvocationManager;
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private RunAsManager runAsManager = new NullRunAsManager();
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
private boolean validateConfigAttributes = true;
.........
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
............
SecurityContextHolder.getContext().setAuthentication(token.getAuthentication());
............
if (afterInvocationManager != null) {
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
}
............
}
protected InterceptorStatusToken beforeInvocation(Object object) {
............
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
............
this.accessDecisionManager.decide(authenticated, object, attr);
............
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
if (runAs == null) {
............
return new InterceptorStatusToken(authenticated, false, attr, object);
} else {
............
SecurityContextHolder.getContext().setAuthentication(runAs);
return new InterceptorStatusToken(authenticated, true, attr, object);
}
............
}
}
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
public void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
&& observeOncePerRequest) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
}
............
}
public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(mi);
try {
result = mi.proceed();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(jp);
try {
result = advisorProceed.proceedWithObject();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware,
MessageSourceAware {
private AccessDecisionManager accessDecisionManager;
private AfterInvocationManager afterInvocationManager;
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private RunAsManager runAsManager = new NullRunAsManager();
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
private boolean validateConfigAttributes = true;
.........
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
............
SecurityContextHolder.getContext().setAuthentication(token.getAuthentication());
............
if (afterInvocationManager != null) {
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
}
............
}
protected InterceptorStatusToken beforeInvocation(Object object) {
............
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
............
this.accessDecisionManager.decide(authenticated, object, attr);
............
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
if (runAs == null) {
............
return new InterceptorStatusToken(authenticated, false, attr, object);
} else {
............
SecurityContextHolder.getContext().setAuthentication(runAs);
return new InterceptorStatusToken(authenticated, true, attr, object);
}
............
}
}
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
public void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
&& observeOncePerRequest) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
}
............
}
public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(mi);
try {
result = mi.proceed();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(jp);
try {
result = advisorProceed.proceedWithObject();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
上面的代码片断已经显示,所有的真正参与验证的代码都在父类AbstractSecurityInterceptor.beforeInvocation()之中进行,而对于拦截器都只是做些委托罢了。这样可以把具体的验证代码同拦截器分开,也有利于扩展,用其他的aop技术或拦截器进行扩展,可以很轻松。
认证体系由AuthenticationManager负责,授权体系由AccessDecisionManager负责,RunAsManager 是作为用户身份转换的手段。AfterInvocationManager留下了一个接口,可以扩展默认的授权体系,可以做一些其他额外的工作。
在AbstractSecurityInterceptor.beforeInvocation()中,
首先进行认证,authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
其次进行授权,this.accessDecisionManager.decide(authenticated, object, attr);
AbstractSecurityInterceptor.afterInvocation()中,
做其他扩展,returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
2,认证体系
2.1认证管理器
认证体系的核心为AuthenticationManager,他的方法authenticate(Authentication authentication)负责所有的认证。在acegi中,由具体类ProviderManager来进行认证过程。
Java代码
public interface AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
public abstract class AbstractAuthenticationManager
implements AuthenticationManager{
public final Authentication authenticate(Authentication authRequest)
throws AuthenticationException {
try {
Authentication authResult = doAuthentication(authRequest);
copyDetails(authRequest, authResult);
return authResult;
} catch (AuthenticationException e) {
e.setAuthentication(authRequest);
throw e;
}
}
private void copyDetails(Authentication source, Authentication dest) {
if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;
token.setDetails(source.getDetails());
}
}
protected abstract Authentication doAuthentication(Authentication authentication)
throws AuthenticationException;
.........
}
public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean,
ApplicationEventPublisherAware, MessageSourceAware {
private List providers;
............
public Authentication doAuthentication(Authentication authentication)
throws AuthenticationException {
.........
Iterator iter = providers.iterator();
............
while (iter.hasNext()) {
.............
AuthenticationProvider provider = (AuthenticationProvider) iter.next();
.........
result = provider.authenticate(authentication);
............
}
............
}
.........
}
public interface AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
public abstract class AbstractAuthenticationManager
implements AuthenticationManager{
public final Authentication authenticate(Authentication authRequest)
throws AuthenticationException {
try {
Authentication authResult = doAuthentication(authRequest);
copyDetails(authRequest, authResult);
return authResult;
} catch (AuthenticationException e) {
e.setAuthentication(authRequest);
throw e;
}
}
private void copyDetails(Authentication source, Authentication dest) {
if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;
token.setDetails(source.getDetails());
}
}
protected abstract Authentication doAuthentication(Authentication authentication)
throws AuthenticationException;
.........
}
public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean,
ApplicationEventPublisherAware, MessageSourceAware {
private List providers;
............
public Authentication doAuthentication(Authentication authentication)
throws AuthenticationException {
.........
Iterator iter = providers.iterator();
............
while (iter.hasNext()) {
.............
AuthenticationProvider provider = (AuthenticationProvider) iter.next();
.........
result = provider.authenticate(authentication);
............
}
............
}
.........
}
从上面代码片断可以看出,真正的认证过程是在ProviderManager.doAuthentication()中进行的。而ProviderManager并不是具体的认证者,他只是个管理器,它要将具体的认证过程委托给具体的认证器提供者AuthenticationProvider去做。
2.2认证提供者
认证提供者就有很多了,可以提供各种各样的认证。如dao,ldap,anonymous,authbyadapter,cas,jaas,remeberme,remote,runnasimpl,testing,x509等。
Java代码
public interface AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException;
public boolean supports(Class authentication);
}
public interface AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException;
public boolean supports(Class authentication);
}
具体的认证提供者类就不详细分析了,只提个名字:DaoAuthenticationProvider,LdapAuthenticationProvider,AnonymousAuthenticationProvider,AuthByAdapterProvider,CasAuthenticationProvider,JaasAuthenticationProvider,RememberMeAuthenticationProvider,RemoteAuthenticationProvider,RunAsImplAuthenticationProvider,TestingAuthenticationProvider,X509AuthenticationProvider。
3,授权体系
3.1授权管理器
授权体系的核心为授权管理器(AccessDecisionManager),它的方法decide(Authentication authentication, Object object, ConfigAttributeDefinition config)进行具体的授权动作。
Java代码
public interface AccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
}
public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean,
MessageSourceAware {
private List decisionVoters;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private boolean allowIfAllAbstainDecisions = false;
public boolean supports(ConfigAttribute attribute) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (voter.supports(attribute)) {
return true;
}
}
return false;
}
public boolean supports(Class clazz) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (!voter.supports(clazz)) {
return false;
}
}
return true;
}
..............
}
public class AffirmativeBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int deny = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class ConsensusBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int grant = 0;
int deny = 0;
int abstain = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
abstain++;
break;
}
}
if (grant > deny) {
return;
}
if (deny > grant) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
} else {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class UnanimousBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
int grant = 0;
int abstain = 0;
Iterator configIter = config.getConfigAttributes();
while (configIter.hasNext()) {
ConfigAttributeDefinition thisDef = new ConfigAttributeDefinition();
thisDef.addConfigAttribute((ConfigAttribute) configIter.next());
Iterator voters = this.getDecisionVoters().iterator();
while (voters.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) voters.next();
int result = voter.vote(authentication, object, thisDef);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
default:
abstain++;
break;
}
}
}
// To get this far, there were no deny votes
if (grant > 0) {
return;
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public interface AccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
}
public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean,
MessageSourceAware {
private List decisionVoters;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private boolean allowIfAllAbstainDecisions = false;
public boolean supports(ConfigAttribute attribute) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (voter.supports(attribute)) {
return true;
}
}
return false;
}
public boolean supports(Class clazz) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (!voter.supports(clazz)) {
return false;
}
}
return true;
}
..............
}
public class AffirmativeBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int deny = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class ConsensusBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int grant = 0;
int deny = 0;
int abstain = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
abstain++;
break;
}
}
if (grant > deny) {
return;
}
if (deny > grant) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
} else {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class UnanimousBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
int grant = 0;
int abstain = 0;
Iterator configIter = config.getConfigAttributes();
while (configIter.hasNext()) {
ConfigAttributeDefinition thisDef = new ConfigAttributeDefinition();
thisDef.addConfigAttribute((ConfigAttribute) configIter.next());
Iterator voters = this.getDecisionVoters().iterator();
while (voters.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) voters.next();
int result = voter.vote(authentication, object, thisDef);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
default:
abstain++;
break;
}
}
}
// To get this far, there were no deny votes
if (grant > 0) {
return;
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
授权管理器AccessDecisionManager默认有三个实现,具体为AffirmativeBased,ConsensusBased,UnanimousBased。三个具体实现都大同小异,主要在具有角色是否应该授权上。
而具体能否单个角色是否授权,是委派给AccessDecisionVoter去做的。
3.2授权投票者
授权投票责的核心是接口AccessDecisionVoter。他有几个具体实现类:BasicAclEntryVoter,AuthenticatedVoter,RoleVoter。
Java代码
public interface AccessDecisionVoter {
public static final int ACCESS_GRANTED = 1;
public static final int ACCESS_ABSTAIN = 0;
public static final int ACCESS_DENIED = -1;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
}
public abstract class AbstractAclVoter implements AccessDecisionVoter {
public boolean supports(Class clazz) {
if (MethodInvocation.class.isAssignableFrom(clazz)) {
return true;
} else if (JoinPoint.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}
}
............
}
public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean {
private AclManager aclManager;
private String internalMethod;
private String processConfigAttribute;
private int[] requirePermission;
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getProcessConfigAttribute())) {
return true;
} else {
return false;
}
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (this.supports(attr)) {
// Need to make an access decision on this invocation
// Attempt to locate the domain object instance to process
Object domainObject = getDomainObjectInstance(object);
// If domain object is null, vote to abstain
if (domainObject == null) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to abstain - domainObject is null");
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
// Evaluate if we are required to use an inner domain object
if ((internalMethod != null) && !"".equals(internalMethod)) {
try {
Class clazz = domainObject.getClass();
Method method = clazz.getMethod(internalMethod, new Class[] {});
domainObject = method.invoke(domainObject, new Object[] {});
} catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ "' does not provide the requested internalMethod: " + internalMethod);
} catch (IllegalAccessException iae) {
if (logger.isDebugEnabled()) {
logger.debug("IllegalAccessException", iae);
if (iae.getCause() != null) {
logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
} catch (InvocationTargetException ite) {
if (logger.isDebugEnabled()) {
logger.debug("InvocationTargetException", ite);
if (ite.getCause() != null) {
logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
}
}
// Obtain the ACLs applicable to the domain object
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
// If principal has no permissions for domain object, deny
if ((acls == null) || (acls.length == 0)) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to deny access - no ACLs returned for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
// Principal has some permissions for domain object, check them
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to grant access");
}
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}
}
// No permissions match
if (logger.isDebugEnabled()) {
logger.debug(
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
...............
}
public class AuthenticatedVoter implements AccessDecisionVoter {
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private boolean isFullyAuthenticated(Authentication authentication) {
return (!authenticationTrustResolver.isAnonymous(authentication)
&& !authenticationTrustResolver.isRememberMe(authentication));
}
public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null");
this.authenticationTrustResolver = authenticationTrustResolver;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {
if (isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isRememberMe(authentication)
|| isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication)
|| authenticationTrustResolver.isRememberMe(authentication)) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public class RoleVoter implements AccessDecisionVoter {
private String rolePrefix = "ROLE_";
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
for (int i = 0; i < authentication.getAuthorities().length; i++) {
if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public interface AccessDecisionVoter {
public static final int ACCESS_GRANTED = 1;
public static final int ACCESS_ABSTAIN = 0;
public static final int ACCESS_DENIED = -1;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
}
public abstract class AbstractAclVoter implements AccessDecisionVoter {
public boolean supports(Class clazz) {
if (MethodInvocation.class.isAssignableFrom(clazz)) {
return true;
} else if (JoinPoint.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}
}
............
}
public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean {
private AclManager aclManager;
private String internalMethod;
private String processConfigAttribute;
private int[] requirePermission;
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getProcessConfigAttribute())) {
return true;
} else {
return false;
}
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (this.supports(attr)) {
// Need to make an access decision on this invocation
// Attempt to locate the domain object instance to process
Object domainObject = getDomainObjectInstance(object);
// If domain object is null, vote to abstain
if (domainObject == null) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to abstain - domainObject is null");
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
// Evaluate if we are required to use an inner domain object
if ((internalMethod != null) && !"".equals(internalMethod)) {
try {
Class clazz = domainObject.getClass();
Method method = clazz.getMethod(internalMethod, new Class[] {});
domainObject = method.invoke(domainObject, new Object[] {});
} catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ "' does not provide the requested internalMethod: " + internalMethod);
} catch (IllegalAccessException iae) {
if (logger.isDebugEnabled()) {
logger.debug("IllegalAccessException", iae);
if (iae.getCause() != null) {
logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
} catch (InvocationTargetException ite) {
if (logger.isDebugEnabled()) {
logger.debug("InvocationTargetException", ite);
if (ite.getCause() != null) {
logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
}
}
// Obtain the ACLs applicable to the domain object
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
// If principal has no permissions for domain object, deny
if ((acls == null) || (acls.length == 0)) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to deny access - no ACLs returned for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
// Principal has some permissions for domain object, check them
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to grant access");
}
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}
}
// No permissions match
if (logger.isDebugEnabled()) {
logger.debug(
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
...............
}
public class AuthenticatedVoter implements AccessDecisionVoter {
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private boolean isFullyAuthenticated(Authentication authentication) {
return (!authenticationTrustResolver.isAnonymous(authentication)
&& !authenticationTrustResolver.isRememberMe(authentication));
}
public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null");
this.authenticationTrustResolver = authenticationTrustResolver;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {
if (isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isRememberMe(authentication)
|| isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication)
|| authenticationTrustResolver.isRememberMe(authentication)) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public class RoleVoter implements AccessDecisionVoter {
private String rolePrefix = "ROLE_";
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
for (int i = 0; i < authentication.getAuthorities().length; i++) {
if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
这三个授权投票实现类中 acl 又最复杂。他会委托给acl管理器(AclManager)来做具体的授权工作。
3.3acl授权体系
AclManager只有一个实现类AclProviderManager ,负责提供acl授权实体。
Java代码
public interface AclManager {
public AclEntry[] getAcls(Object domainInstance);
public AclEntry[] getAcls(Object domainInstance, Authentication authentication);
}
public class AclProviderManager implements AclManager, InitializingBean {
public AclEntry[] getAcls(Object domainInstance) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
Iterator iter = providers.iterator();
while (iter.hasNext()) {
AclProvider provider = (AclProvider) iter.next();
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance);
}
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
Assert.notNull(authentication, "authentication is null - violating interface contract");
Iterator iter = providers.iterator();
while (iter.hasNext()) {
AclProvider provider = (AclProvider) iter.next();
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance, authentication);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Provider " + provider.toString() + " does not support " + domainInstance);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
.........
}
这几天对acegi研究了一下,现对这几天的研究做个总结。
网上资料对于acegi在web上的应用非常多,所以特意不从web入手,而从一般的java方法入手。
acegi的基本原理就是利用拦截器,对请求进行拦截,在拦截前和拦截后做些安全验证,以达到安全目的。所谓安全,一般包括两个部分,一为认证(authentication),二为授权(authorization)。
1,拦截器体系
acegi中拦截器为分为三类:
(1)filter拦截器(FilterSecurityInterceptor),主要对web应用进行拦截,即利用servlet的filter进行拦截。
(2)method拦截器,分为spring的method拦截器(MethodSecurityInterceptor)和aspectj的method拦截器(AspectJSecurityInterceptor)。
Java代码
public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware,
MessageSourceAware {
private AccessDecisionManager accessDecisionManager;
private AfterInvocationManager afterInvocationManager;
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private RunAsManager runAsManager = new NullRunAsManager();
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
private boolean validateConfigAttributes = true;
.........
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
............
SecurityContextHolder.getContext().setAuthentication(token.getAuthentication());
............
if (afterInvocationManager != null) {
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
}
............
}
protected InterceptorStatusToken beforeInvocation(Object object) {
............
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
............
this.accessDecisionManager.decide(authenticated, object, attr);
............
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
if (runAs == null) {
............
return new InterceptorStatusToken(authenticated, false, attr, object);
} else {
............
SecurityContextHolder.getContext().setAuthentication(runAs);
return new InterceptorStatusToken(authenticated, true, attr, object);
}
............
}
}
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
public void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
&& observeOncePerRequest) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
}
............
}
public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(mi);
try {
result = mi.proceed();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(jp);
try {
result = advisorProceed.proceedWithObject();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware,
MessageSourceAware {
private AccessDecisionManager accessDecisionManager;
private AfterInvocationManager afterInvocationManager;
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private RunAsManager runAsManager = new NullRunAsManager();
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
private boolean validateConfigAttributes = true;
.........
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
............
SecurityContextHolder.getContext().setAuthentication(token.getAuthentication());
............
if (afterInvocationManager != null) {
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
}
............
}
protected InterceptorStatusToken beforeInvocation(Object object) {
............
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
............
this.accessDecisionManager.decide(authenticated, object, attr);
............
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
if (runAs == null) {
............
return new InterceptorStatusToken(authenticated, false, attr, object);
} else {
............
SecurityContextHolder.getContext().setAuthentication(runAs);
return new InterceptorStatusToken(authenticated, true, attr, object);
}
............
}
}
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
public void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
&& observeOncePerRequest) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
}
............
}
public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(mi);
try {
result = mi.proceed();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
Object result = null;
InterceptorStatusToken token = super.beforeInvocation(jp);
try {
result = advisorProceed.proceedWithObject();
} finally {
result = super.afterInvocation(token, result);
}
return result;
}
............
}
上面的代码片断已经显示,所有的真正参与验证的代码都在父类AbstractSecurityInterceptor.beforeInvocation()之中进行,而对于拦截器都只是做些委托罢了。这样可以把具体的验证代码同拦截器分开,也有利于扩展,用其他的aop技术或拦截器进行扩展,可以很轻松。
认证体系由AuthenticationManager负责,授权体系由AccessDecisionManager负责,RunAsManager 是作为用户身份转换的手段。AfterInvocationManager留下了一个接口,可以扩展默认的授权体系,可以做一些其他额外的工作。
在AbstractSecurityInterceptor.beforeInvocation()中,
首先进行认证,authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());
其次进行授权,this.accessDecisionManager.decide(authenticated, object, attr);
AbstractSecurityInterceptor.afterInvocation()中,
做其他扩展,returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),token.getAttr(), returnedObject);
2,认证体系
2.1认证管理器
认证体系的核心为AuthenticationManager,他的方法authenticate(Authentication authentication)负责所有的认证。在acegi中,由具体类ProviderManager来进行认证过程。
Java代码
public interface AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
public abstract class AbstractAuthenticationManager
implements AuthenticationManager{
public final Authentication authenticate(Authentication authRequest)
throws AuthenticationException {
try {
Authentication authResult = doAuthentication(authRequest);
copyDetails(authRequest, authResult);
return authResult;
} catch (AuthenticationException e) {
e.setAuthentication(authRequest);
throw e;
}
}
private void copyDetails(Authentication source, Authentication dest) {
if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;
token.setDetails(source.getDetails());
}
}
protected abstract Authentication doAuthentication(Authentication authentication)
throws AuthenticationException;
.........
}
public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean,
ApplicationEventPublisherAware, MessageSourceAware {
private List providers;
............
public Authentication doAuthentication(Authentication authentication)
throws AuthenticationException {
.........
Iterator iter = providers.iterator();
............
while (iter.hasNext()) {
.............
AuthenticationProvider provider = (AuthenticationProvider) iter.next();
.........
result = provider.authenticate(authentication);
............
}
............
}
.........
}
public interface AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
public abstract class AbstractAuthenticationManager
implements AuthenticationManager{
public final Authentication authenticate(Authentication authRequest)
throws AuthenticationException {
try {
Authentication authResult = doAuthentication(authRequest);
copyDetails(authRequest, authResult);
return authResult;
} catch (AuthenticationException e) {
e.setAuthentication(authRequest);
throw e;
}
}
private void copyDetails(Authentication source, Authentication dest) {
if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;
token.setDetails(source.getDetails());
}
}
protected abstract Authentication doAuthentication(Authentication authentication)
throws AuthenticationException;
.........
}
public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean,
ApplicationEventPublisherAware, MessageSourceAware {
private List providers;
............
public Authentication doAuthentication(Authentication authentication)
throws AuthenticationException {
.........
Iterator iter = providers.iterator();
............
while (iter.hasNext()) {
.............
AuthenticationProvider provider = (AuthenticationProvider) iter.next();
.........
result = provider.authenticate(authentication);
............
}
............
}
.........
}
从上面代码片断可以看出,真正的认证过程是在ProviderManager.doAuthentication()中进行的。而ProviderManager并不是具体的认证者,他只是个管理器,它要将具体的认证过程委托给具体的认证器提供者AuthenticationProvider去做。
2.2认证提供者
认证提供者就有很多了,可以提供各种各样的认证。如dao,ldap,anonymous,authbyadapter,cas,jaas,remeberme,remote,runnasimpl,testing,x509等。
Java代码
public interface AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException;
public boolean supports(Class authentication);
}
public interface AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException;
public boolean supports(Class authentication);
}
具体的认证提供者类就不详细分析了,只提个名字:DaoAuthenticationProvider,LdapAuthenticationProvider,AnonymousAuthenticationProvider,AuthByAdapterProvider,CasAuthenticationProvider,JaasAuthenticationProvider,RememberMeAuthenticationProvider,RemoteAuthenticationProvider,RunAsImplAuthenticationProvider,TestingAuthenticationProvider,X509AuthenticationProvider。
3,授权体系
3.1授权管理器
授权体系的核心为授权管理器(AccessDecisionManager),它的方法decide(Authentication authentication, Object object, ConfigAttributeDefinition config)进行具体的授权动作。
Java代码
public interface AccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
}
public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean,
MessageSourceAware {
private List decisionVoters;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private boolean allowIfAllAbstainDecisions = false;
public boolean supports(ConfigAttribute attribute) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (voter.supports(attribute)) {
return true;
}
}
return false;
}
public boolean supports(Class clazz) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (!voter.supports(clazz)) {
return false;
}
}
return true;
}
..............
}
public class AffirmativeBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int deny = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class ConsensusBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int grant = 0;
int deny = 0;
int abstain = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
abstain++;
break;
}
}
if (grant > deny) {
return;
}
if (deny > grant) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
} else {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class UnanimousBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
int grant = 0;
int abstain = 0;
Iterator configIter = config.getConfigAttributes();
while (configIter.hasNext()) {
ConfigAttributeDefinition thisDef = new ConfigAttributeDefinition();
thisDef.addConfigAttribute((ConfigAttribute) configIter.next());
Iterator voters = this.getDecisionVoters().iterator();
while (voters.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) voters.next();
int result = voter.vote(authentication, object, thisDef);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
default:
abstain++;
break;
}
}
}
// To get this far, there were no deny votes
if (grant > 0) {
return;
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public interface AccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
}
public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean,
MessageSourceAware {
private List decisionVoters;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private boolean allowIfAllAbstainDecisions = false;
public boolean supports(ConfigAttribute attribute) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (voter.supports(attribute)) {
return true;
}
}
return false;
}
public boolean supports(Class clazz) {
Iterator iter = this.decisionVoters.iterator();
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
if (!voter.supports(clazz)) {
return false;
}
}
return true;
}
..............
}
public class AffirmativeBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int deny = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class ConsensusBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
Iterator iter = this.getDecisionVoters().iterator();
int grant = 0;
int deny = 0;
int abstain = 0;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
abstain++;
break;
}
}
if (grant > deny) {
return;
}
if (deny > grant) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
} else {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
public class UnanimousBased extends AbstractAccessDecisionManager {
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException {
int grant = 0;
int abstain = 0;
Iterator configIter = config.getConfigAttributes();
while (configIter.hasNext()) {
ConfigAttributeDefinition thisDef = new ConfigAttributeDefinition();
thisDef.addConfigAttribute((ConfigAttribute) configIter.next());
Iterator voters = this.getDecisionVoters().iterator();
while (voters.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) voters.next();
int result = voter.vote(authentication, object, thisDef);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
default:
abstain++;
break;
}
}
}
// To get this far, there were no deny votes
if (grant > 0) {
return;
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
..............
}
授权管理器AccessDecisionManager默认有三个实现,具体为AffirmativeBased,ConsensusBased,UnanimousBased。三个具体实现都大同小异,主要在具有角色是否应该授权上。
而具体能否单个角色是否授权,是委派给AccessDecisionVoter去做的。
3.2授权投票者
授权投票责的核心是接口AccessDecisionVoter。他有几个具体实现类:BasicAclEntryVoter,AuthenticatedVoter,RoleVoter。
Java代码
public interface AccessDecisionVoter {
public static final int ACCESS_GRANTED = 1;
public static final int ACCESS_ABSTAIN = 0;
public static final int ACCESS_DENIED = -1;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
}
public abstract class AbstractAclVoter implements AccessDecisionVoter {
public boolean supports(Class clazz) {
if (MethodInvocation.class.isAssignableFrom(clazz)) {
return true;
} else if (JoinPoint.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}
}
............
}
public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean {
private AclManager aclManager;
private String internalMethod;
private String processConfigAttribute;
private int[] requirePermission;
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getProcessConfigAttribute())) {
return true;
} else {
return false;
}
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (this.supports(attr)) {
// Need to make an access decision on this invocation
// Attempt to locate the domain object instance to process
Object domainObject = getDomainObjectInstance(object);
// If domain object is null, vote to abstain
if (domainObject == null) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to abstain - domainObject is null");
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
// Evaluate if we are required to use an inner domain object
if ((internalMethod != null) && !"".equals(internalMethod)) {
try {
Class clazz = domainObject.getClass();
Method method = clazz.getMethod(internalMethod, new Class[] {});
domainObject = method.invoke(domainObject, new Object[] {});
} catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ "' does not provide the requested internalMethod: " + internalMethod);
} catch (IllegalAccessException iae) {
if (logger.isDebugEnabled()) {
logger.debug("IllegalAccessException", iae);
if (iae.getCause() != null) {
logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
} catch (InvocationTargetException ite) {
if (logger.isDebugEnabled()) {
logger.debug("InvocationTargetException", ite);
if (ite.getCause() != null) {
logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
}
}
// Obtain the ACLs applicable to the domain object
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
// If principal has no permissions for domain object, deny
if ((acls == null) || (acls.length == 0)) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to deny access - no ACLs returned for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
// Principal has some permissions for domain object, check them
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to grant access");
}
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}
}
// No permissions match
if (logger.isDebugEnabled()) {
logger.debug(
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
...............
}
public class AuthenticatedVoter implements AccessDecisionVoter {
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private boolean isFullyAuthenticated(Authentication authentication) {
return (!authenticationTrustResolver.isAnonymous(authentication)
&& !authenticationTrustResolver.isRememberMe(authentication));
}
public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null");
this.authenticationTrustResolver = authenticationTrustResolver;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {
if (isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isRememberMe(authentication)
|| isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication)
|| authenticationTrustResolver.isRememberMe(authentication)) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public class RoleVoter implements AccessDecisionVoter {
private String rolePrefix = "ROLE_";
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
for (int i = 0; i < authentication.getAuthorities().length; i++) {
if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public interface AccessDecisionVoter {
public static final int ACCESS_GRANTED = 1;
public static final int ACCESS_ABSTAIN = 0;
public static final int ACCESS_DENIED = -1;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
}
public abstract class AbstractAclVoter implements AccessDecisionVoter {
public boolean supports(Class clazz) {
if (MethodInvocation.class.isAssignableFrom(clazz)) {
return true;
} else if (JoinPoint.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}
}
............
}
public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean {
private AclManager aclManager;
private String internalMethod;
private String processConfigAttribute;
private int[] requirePermission;
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getProcessConfigAttribute())) {
return true;
} else {
return false;
}
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (this.supports(attr)) {
// Need to make an access decision on this invocation
// Attempt to locate the domain object instance to process
Object domainObject = getDomainObjectInstance(object);
// If domain object is null, vote to abstain
if (domainObject == null) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to abstain - domainObject is null");
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
// Evaluate if we are required to use an inner domain object
if ((internalMethod != null) && !"".equals(internalMethod)) {
try {
Class clazz = domainObject.getClass();
Method method = clazz.getMethod(internalMethod, new Class[] {});
domainObject = method.invoke(domainObject, new Object[] {});
} catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ "' does not provide the requested internalMethod: " + internalMethod);
} catch (IllegalAccessException iae) {
if (logger.isDebugEnabled()) {
logger.debug("IllegalAccessException", iae);
if (iae.getCause() != null) {
logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
} catch (InvocationTargetException ite) {
if (logger.isDebugEnabled()) {
logger.debug("InvocationTargetException", ite);
if (ite.getCause() != null) {
logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
}
}
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ " for object: " + domainObject);
}
}
// Obtain the ACLs applicable to the domain object
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
// If principal has no permissions for domain object, deny
if ((acls == null) || (acls.length == 0)) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to deny access - no ACLs returned for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
// Principal has some permissions for domain object, check them
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
if (logger.isDebugEnabled()) {
logger.debug("Voting to grant access");
}
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}
}
// No permissions match
if (logger.isDebugEnabled()) {
logger.debug(
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
}
return AccessDecisionVoter.ACCESS_DENIED;
}
}
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
...............
}
public class AuthenticatedVoter implements AccessDecisionVoter {
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private boolean isFullyAuthenticated(Authentication authentication) {
return (!authenticationTrustResolver.isAnonymous(authentication)
&& !authenticationTrustResolver.isRememberMe(authentication));
}
public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null");
this.authenticationTrustResolver = authenticationTrustResolver;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())
|| IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {
if (isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isRememberMe(authentication)
|| isFullyAuthenticated(authentication)) {
return ACCESS_GRANTED;
}
}
if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {
if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication)
|| authenticationTrustResolver.isRememberMe(authentication)) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
public class RoleVoter implements AccessDecisionVoter {
private String rolePrefix = "ROLE_";
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
} else {
return false;
}
}
public boolean supports(Class clazz) {
return true;
}
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
for (int i = 0; i < authentication.getAuthorities().length; i++) {
if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
这三个授权投票实现类中 acl 又最复杂。他会委托给acl管理器(AclManager)来做具体的授权工作。
3.3acl授权体系
AclManager只有一个实现类AclProviderManager ,负责提供acl授权实体。
Java代码
public interface AclManager {
public AclEntry[] getAcls(Object domainInstance);
public AclEntry[] getAcls(Object domainInstance, Authentication authentication);
}
public class AclProviderManager implements AclManager, InitializingBean {
public AclEntry[] getAcls(Object domainInstance) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
Iterator iter = providers.iterator();
while (iter.hasNext()) {
AclProvider provider = (AclProvider) iter.next();
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance);
}
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
Assert.notNull(authentication, "authentication is null - violating interface contract");
Iterator iter = providers.iterator();
while (iter.hasNext()) {
AclProvider provider = (AclProvider) iter.next();
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance, authentication);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Provider " + provider.toString() + " does not support " + domainInstance);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
.........
}
发表评论
-
菜鸟-手把手教你把Acegi应用到实际项目中(1.1)
2009-08-25 09:55 785相信不少朋友们对于学习Acegi的过程是比较痛苦的,而且可能最 ... -
再论 Acegi 权限存储策略 (转载)
2007-10-29 13:57 1190在我之前的一篇文章里, 说明了在 Acegi 中如何将资源权限 ... -
学习acegi-security (转载)
2007-10-29 13:52 1190学习acegi-security 这几天对acegi研究了一 ... -
Acegi安全框架能解决和不能解决的安全问题 (转载)
2007-10-29 13:48 997就我目前对Acegi的了解,Acegi安全框架主要解决的安全问 ... -
Acegi配置文档(转载)
2007-10-29 13:44 1246作者:javafish(likunkun) Em ... -
Acegi学习小结 (转载)
2007-10-29 13:37 843一、基本原理 Acegi认证 ... -
学习Acegi-认证(authentication) (转载)
2007-10-29 13:36 1044最近两星期在学习acegi,过程中感谢JavaEye,Spri ...
相关推荐
2. **学习网址**:提供了一个适合初学者的基础教程,从零开始学习Acegi的用法和配置。这个网站可能包含了详细的教程、示例代码和常见问题解答,帮助你快速上手Acegi。 如果你在学习过程中遇到任何问题,可以通过...
### Acegi认证服务详解 #### 一、Acegi简介与背景 Acegi是Spring Security的前身,是一款基于Spring框架的安全管理工具,旨在为应用程序提供安全控制...希望本文能够为正在学习或使用Acegi的同学提供有价值的参考。
首先,"学习ACEGI - - New - JavaEye论坛.mht"可能是一个关于Acegi的入门教程,涵盖了Acegi的基本概念和如何在项目中引入Acegi。JavaEye论坛是一个知名的Java开发者社区,其中的帖子通常包含丰富的实践经验和问题...
Acegi 是一个在Java开发领域,特别是Spring框架中曾经广泛使用的安全组件,全称为Acegi Security。...学习Acegi可以帮助我们更好地理解Spring Security的工作原理,从而提升我们的应用安全开发能力。
通过学习Acegi,我们可以了解到Web应用安全的基本思路和实践方法,这对于理解现代的Spring Security框架非常有帮助。虽然Acegi已经不再更新,但它的理念和架构仍对现代安全框架设计产生深远影响。
"Acegi学习笔记.doc"可能包含个人学习Acegi的过程中积累的经验和技巧,这些笔记通常会涵盖实践中的问题解决和案例分析。笔记中可能包含了如何配置Acegi以保护特定的Spring Bean,以及如何定义自定义的权限表达式,...
通过深入学习Acegi,你可以了解Spring Security的基本架构和原理,这对于理解现代的Spring Security配置和使用非常有帮助。尽管Acegi已不再更新,但其思想和技术仍在Spring Security中得到沿用和发展。如果你正在...
"acegisample"可能是一个解压后的war文件内容,包含了Web应用的所有源代码和资源文件,方便开发者查看和学习Acegi和LDAP的集成方式。 通过这个实例,开发者可以学习如何配置Acegi的安全策略,如何在Spring应用中...
Acegi学习 Acegi是Spring Security的前身,它是一个强大且灵活的安全框架,用于Java企业级应用程序。在本文中,我们将深入探讨Acegi的...通过深入学习Acegi,开发者能够更好地掌握企业级应用中的安全性设计和实践。
学习Acegi不仅能够提升你的Java安全开发能力,也有助于理解Spring Security的底层原理,因为许多核心概念在Spring Security中依然保留。通过实践Acegi提供的例子,你可以更好地理解和掌握这些概念,从而在实际项目中...
`学习Acegi-认证(authentication).mht`文件可能详细讲解了Acegi的认证机制,包括基于内存、数据库、LDAP等不同源的身份验证策略。 总的来说,这个压缩包提供了全面的Acegi学习资源,涵盖了从基础概念到高级特性的...
学习acegi的第一步, <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,basicProcessingFilter,...
Acegi是Spring Security的前身,它是一个用于Java平台的安全框架,专为Spring应用程序设计。本教程将引导初学者逐步了解如何在实际项目中应用...同时,学习Acegi也能为理解和使用现代的Spring Security打下坚实的基础。
在本教程中,作者旨在帮助那些在学习Acegi过程中遇到困难的开发者,通过一步步的指导,使他们能够成功地将Acegi集成到实际项目中,并理解其核心配置和工作原理。 首先,Acegi的配置是其难点之一,因为涉及许多不同...
Acegi Security System for Spring 是一个历史悠久的Java安全框架,它...尽管Acegi已经被Spring Security所取代,但其核心理念和设计模式在现代安全框架中依然得到沿用,因此学习Acegi仍能提升你对Java安全体系的理解。
尽管如此,学习Acegi仍能帮助理解Spring Security的基础概念和设计模式,因为两者的核心思想是一致的。在实际开发中,建议使用最新版本的Spring Security,以获取更好的支持和更先进的安全特性。
在本实例中,我们将深入探讨如何使用Acegi进行权限管理,以及如何通过一个简单的项目来学习Acegi的核心功能。 首先,Acegi提供了一种灵活的方式来定义用户角色和权限,允许我们基于角色的访问控制(RBAC)。在这个...
Acegi安全框架是一款基于Spring AOP(面向切面编程)的高级安全认证和授权框架,它为Java应用程序提供了全面的安全管理...通过学习Acegi,开发者不仅可以提升应用的安全性,还能掌握面向切面编程在实际项目中的应用。
Acegi是Spring Security的前身,它是一个强大的、可...尽管Acegi已被Spring Security所取代,但其核心理念和使用方法在Spring Security中仍然得到延续,因此学习Acegi对于理解Spring Security的安全机制非常有帮助。
Acegi安全权限管理手册是一本全面介绍Acegi安全框架在...通过学习Acegi安全权限管理手册,开发者不仅可以掌握Acegi Security的使用,还能了解到安全设计的最佳实践,从而为开发更安全、健壮的应用程序打下坚实基础。