[Spring3.x源码]Ageci(二)授权器

上一篇中配置的FilterSecurityInterceptor即是授权器

FilterSecurityInterceptor.doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
	FilterInvocation fi = new FilterInvocation(request, response, chain);
	invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
        if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
            && observeOncePerRequest) {
            // filter already applied to this request and user wants us to observce
            // once-per-request handling, so don't re-do security checking
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } else {
            // first time this request being called, so perform security checking
            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);
            }
        }
    }
1.InterceptorStatusToken token = super.beforeInvocation(fi);

	protected InterceptorStatusToken beforeInvocation(Object object) {
		Assert.notNull(object, "Object was null");
	
		if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {
			throw new IllegalArgumentException("Security invocation attempted for object "
					+ object.getClass().getName()
					+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "
					+ getSecureObjectClass());
		}
	
		ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object);
	
		if (attr == null) {
			if (rejectPublicInvocations) {
				throw new IllegalArgumentException(
						"No public invocations are allowed via this AbstractSecurityInterceptor. "
								+ "This indicates a configuration error because the "
								+ "AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
			}
	
			if (logger.isDebugEnabled()) {
				logger.debug("Public object - authentication not attempted");
			}
	
			publishEvent(new PublicInvocationEvent(object));
	
			return null; // no further work post-invocation
		}
	
		if (logger.isDebugEnabled()) {
			logger.debug("Secure object: " + object.toString() + "; ConfigAttributes: " + attr.toString());
		}
	
		if (SecurityContextHolder.getContext().getAuthentication() == null) {
			credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound",
					"An Authentication object was not found in the SecurityContext"), object, attr);
		}
	
		// Attempt authentication if not already authenticated, or user always
		// wants reauthentication
		Authentication authenticated;
	
		if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated() || alwaysReauthenticate) {
			try {
				authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
						.getAuthentication());
			}
			catch (AuthenticationException authenticationException) {
				throw authenticationException;
			}
	
			// We don't authenticated.setAuthentication(true), because each
			// provider should do that
			if (logger.isDebugEnabled()) {
				logger.debug("Successfully Authenticated: " + authenticated.toString());
			}
	
			SecurityContextHolder.getContext().setAuthentication(authenticated);
		}
		else {
			authenticated = SecurityContextHolder.getContext().getAuthentication();
	
			if (logger.isDebugEnabled()) {
				logger.debug("Previously Authenticated: " + authenticated.toString());
			}
		}
	
		// Attempt authorization
		try {
			this.accessDecisionManager.decide(authenticated, object, attr);
		}
		catch (AccessDeniedException accessDeniedException) {
			AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated,
					accessDeniedException);
			publishEvent(event);
	
			throw accessDeniedException;
		}
	
		if (logger.isDebugEnabled()) {
			logger.debug("Authorization successful");
		}
	
		AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated);
		publishEvent(event);
	
		// Attempt to run as a different user
		Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
	
		if (runAs == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("RunAsManager did not change Authentication object");
			}
	
			// no further work post-invocation
			return new InterceptorStatusToken(authenticated, false, attr, object);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Switching to RunAs Authentication: " + runAs.toString());
			}
	
			SecurityContextHolder.getContext().setAuthentication(runAs);
	
			// revert to token.Authenticated post-invocation
			return new InterceptorStatusToken(authenticated, true, attr, object);
		}
	}
1.1、ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object);
解析配置文件中配置到objectDefinitionSource对象中的值。

之后去SecurityContextHolder中获取Authentication对象。如果没有的话,要解析一次。而SecurityContextHolder中的Authentication对象是在上一篇,验证成功后AbstractProcessingFilter.successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
    Authentication authResult)方法中保存进去的。

1.2、this.accessDecisionManager.decide(authenticated, object, attr);
private AccessDecisionManager accessDecisionManager;来自配置文件accessDecisionManager
以AffirmativeBased为例,一票否决制:

	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();
	}
this.getDecisionVoters().iterator(),遍历投票器
也是在配置文件中配置,以AuthenticatedVoter为例

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 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 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";
当然,我们也可以写自己的Voter,加到配置中,完成相关业务操作。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值