Spring Security详解(四)认证之鉴权

4 鉴权

从Spring Security的过滤器链中,我们已经发现位于最后的FilterSecurityInterceptor是用来进行权限认证的,这一节将详细分析Spring Security是如何进行权限认证的。

4.1 FilterSecurityInterceptor

源码分析:

public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements
    Filter {
   
   
    private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
    ...
        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 observe
            // once-per-request handling, so don't re-do security checking
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        }
        else {
   
   
            //第一次调用此请求时,请执行安全检查
            if (fi.getRequest() != null && observeOncePerRequest) {
   
   
                fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
            }
			
            //before
            InterceptorStatusToken token = super.beforeInvocation(fi);

            try {
   
   
                //过滤器链
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            }
            finally {
   
   
                //finally
                super.finallyInvocation(token);
            }
			//after
            super.afterInvocation(token, null);
        }
    }
}

这段代码的主要逻辑就是调用了父类的beforeInvocation、开启filter链式调用、finallyInvocationafterInvocation方法。filter的链式调用就是获取配置好的filter,按照顺序依次进行调用,接下来重点看一下父类做了什么。

AbstractSecurityInterceptor

AbstractSecurityInterceptor是一个实现了对受保护对象的访问进行拦截的抽象类,先来看一下它的源码:

public abstract class AbstractSecurityInterceptor implements InitializingBean,
		ApplicationEventPublisherAware, MessageSourceAware {
   
   
	...
	//对返回值进行修改
	private AfterInvocationManager afterInvocationManager;
	//改变鉴权过后的Authentication
	private RunAsManager runAsManager = new NullRunAsManager();
	...
	
	protected InterceptorStatusToken beforeInvocation(Object object) {
   
   
		...
		//获取配置的权限信息
		Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource()
				.getAttributes(object);
		...
		//身份认证是否完成
		Authentication authenticated = authenticateIfRequired();
		try {
   
   
			//资源权限认证
			this.accessDecisionManager.decide(authenticated, object, attributes);
		}
		...
		// Attempt to run as a different user
		//修改保存在SecurityContext中的Authentication
		Authentication runAs = this.runAsManager.buildRunAs(authenticated, object,
				attributes);
		...
	}

	//请求完毕后进行清理
	protected void finallyInvocation(InterceptorStatusToken token) {
   
   
		if (token != null && token.isContextHolderRefreshRequired()) {
   
   
			...
			SecurityContextHolder.setContext(token.getSecurityContext());
		}
	}

	
	protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
   
   
		finallyInvocation(token); // continue to clean in this method for passivity
		if (afterInvocationManager != null) {
   
   
			// Attempt after invocation handling
			try {
   
   
                //重点
				returnedObject = afterInvocationManager.decide(token.getSecurityContext()
						.getAuthentication(), token.getSecureObject(), token
						.getAttributes(), returnedObject);
			}
			...
		}

		return returnedObject;
	}

	private Authentication authenticateIfRequired() {
   
   
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		//判断身份认证是否完成
		if (authentication.isAuthenticated() && !alwaysReauthenticate) {
   
   
			return
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值