• Spring Security 源码学习(二): Spring Security自动配置(初始化流程)


    【深度好文】: 「和耳朵」SpringSecurity是如何代理过滤器链的?

    1. 自动配置security的bean信息

    SpringBoot自动配置实现原理

    下面是 Spring Boot autoconfigure 自动创建的配置类信息

    2. springSecurityFilterChain 初始化

    1. springSecurityFilterChain 定义

    WebSecurityConfiguration中定义了 springSecurityFilterChain 这个bean

    @Configuration(proxyBeanMethods = false)
    public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
    
    	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    	public Filter springSecurityFilterChain() throws Exception {
    		boolean hasConfigurers = webSecurityConfigurers != null
    				&& !webSecurityConfigurers.isEmpty();
    		if (!hasConfigurers) {
    			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
    					.postProcess(new WebSecurityConfigurerAdapter() {
    					});
    			webSecurity.apply(adapter);
    		}
    		return webSecurity.build();
    	}
    }
    
    

    2. springSecurityFilterChain 初始化

    待补充

    3. springSecurityFilterChain 如何被添加到Filter

    创建一个 targetBeanName 属性值为 springSecurityFilterChain 的 DelegatingFilterProxy Filter 实例, 并注册到 ServletContext

    1. AbstractSecurityWebApplicationInitializer

    public abstract class AbstractSecurityWebApplicationInitializer
    		implements WebApplicationInitializer {
    			
    	public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";
    	
    	public final void onStartup(ServletContext servletContext) {
    		beforeSpringSecurityFilterChain(servletContext);
    		if (this.configurationClasses != null) {
    			AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
    			rootAppContext.register(this.configurationClasses);
    			servletContext.addListener(new ContextLoaderListener(rootAppContext));
    		}
    		if (enableHttpSessionEventPublisher()) {
    			servletContext.addListener(
    					"org.springframework.security.web.session.HttpSessionEventPublisher");
    		}
    		servletContext.setSessionTrackingModes(getSessionTrackingModes());
    		insertSpringSecurityFilterChain(servletContext);
    		afterSpringSecurityFilterChain(servletContext);
    	}
    	
    	 /**
    	  * 创建一个 DelegatingFilterProxy 实例注册 Filter
    	  */
    	private void insertSpringSecurityFilterChain(ServletContext servletContext) {
    		String filterName = DEFAULT_FILTER_NAME;
    		DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(
    				filterName);
    		String contextAttribute = getWebApplicationContextAttribute();
    		if (contextAttribute != null) {
    			springSecurityFilterChain.setContextAttribute(contextAttribute);
    		}
    		registerFilter(servletContext, true, filterName, springSecurityFilterChain);
    	}
    	
    	 /**
    	  * 将 DelegatingFilterProxy 添加到 ServletContext 的 Filter中
    	  */
    	private void registerFilter(ServletContext servletContext,
    								boolean insertBeforeOtherFilters, String filterName, Filter filter) {
    		Dynamic registration = servletContext.addFilter(filterName, filter);
    		if (registration == null) {
    			throw new IllegalStateException(
    					"Duplicate Filter registration for '" + filterName
    							+ "'. Check to ensure the Filter is only configured once.");
    		}
    		registration.setAsyncSupported(isAsyncSecuritySupported());
    		EnumSet<DispatcherType> dispatcherTypes = getSecurityDispatcherTypes();
    		registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters,
    				"/*");
    	}
    }
    

    4. springSecurityFilterChain 如何工作

    DelegatingFilterProxy 在请求第一次到来时初始化, 从应用中获取bean名称为 springSecurityFilterChain 的实例, 然后调用 springSecurityFilterChain 的 doFilter 方法

    public class DelegatingFilterProxy extends GenericFilterBean {
    
    
    	@Nullable
    	private String targetBeanName;
    
    	@Nullable
    	private volatile Filter delegate;
    	
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
    			throws ServletException, IOException {
    
    		// 懒加载,使用时进行初始化
    		Filter delegateToUse = this.delegate;
    		if (delegateToUse == null) {
    			// 初始化 delegate
    			synchronized (this.delegateMonitor) {
    				delegateToUse = this.delegate;
    				if (delegateToUse == null) {
    					WebApplicationContext wac = findWebApplicationContext();
    					if (wac == null) {
    						throw new IllegalStateException("No WebApplicationContext found: " +
    								"no ContextLoaderListener or DispatcherServlet registered?");
    					}
    					delegateToUse = initDelegate(wac);
    				}
    				this.delegate = delegateToUse;
    			}
    		}
    		 // 调用 springSecurityFilterChain 的 doFilter()
    		invokeDelegate(delegateToUse, request, response, filterChain);
    	}
    	
    	protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    		String targetBeanName = getTargetBeanName();
    		Assert.state(targetBeanName != null, "No target bean name set");
    		// 根据 bean 名称获取实例对象
    		Filter delegate = wac.getBean(targetBeanName, Filter.class);
    		if (isTargetFilterLifecycle()) {
    			delegate.init(getFilterConfig());
    		}
    		return delegate;
    	}
    }
    
  • 相关阅读:
    【Luogu1095】守望者的逃离
    python基础学习1-类相关内置函数
    python基础学习1-面向对象
    python基础学习1 -异常捕获
    python基础学习1-类,对象
    python基础学习1-正则表达式
    python基础学习1-反射
    python基础学习1-日志信息
    python基础学习1-生成器,递归函数
    python基础学习1-json,pickle的序列化和反序列化
  • 原文地址:https://www.cnblogs.com/virgosnail/p/16283454.html
Copyright © 2020-2023  润新知