spring-security源码-如何初始化SecurityFilterChain到Servlet
1.SecurityFilterChain是由HttpSecurty根据各个config配置生成的Filter
SecurityFilterChain是接口,默认实现是由DefaultSecurityFilterChain
SecurityFilterChain只充当描述的作用,描述哪些url走这批filter
public final class DefaultSecurityFilterChain implements SecurityFilterChain { private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class); //匹配url 多套url登录逻辑由这里实现 默认/** 比如/product /user 逻辑相互隔离 private final RequestMatcher requestMatcher; //相关servlet private final List<Filter> filters; public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) { this(requestMatcher, Arrays.asList(filters)); } public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) { if (filters.isEmpty()) { logger.info(LogMessage.format("Will not secure %s", requestMatcher)); } else { logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters)); } this.requestMatcher = requestMatcher; this.filters = new ArrayList(filters); } public RequestMatcher getRequestMatcher() { return this.requestMatcher; } public List<Filter> getFilters() { return this.filters; } public boolean matches(HttpServletRequest request) { return this.requestMatcher.matches(request); } public String toString() { return this.getClass().getSimpleName() + " [RequestMatcher=" + this.requestMatcher + ", Filters=" + this.filters + "]"; } }
2.初始化是通过
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration 实现
@AutoConfiguration(after = SecurityAutoConfiguration.class) @ConditionalOnWebApplication(type = Type.SERVLET) @EnableConfigurationProperties(SecurityProperties.class) @ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class }) public class SecurityFilterAutoConfiguration { private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME; //存在 springSecurityFilterChain @Bean @ConditionalOnBean(name = DEFAULT_FILTER_NAME) public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration( SecurityProperties securityProperties) {
//<3> DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean( DEFAULT_FILTER_NAME); registration.setOrder(securityProperties.getFilter().getOrder()); registration.setDispatcherTypes(getDispatcherTypes(securityProperties)); return registration; } private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) { if (securityProperties.getFilter().getDispatcherTypes() == null) { return null; } return securityProperties.getFilter() .getDispatcherTypes() .stream() .map((type) -> DispatcherType.valueOf(type.name())) .collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class))); } }
<3>
委托给DelegatingFilterProxyRegistrationBean
他是 org.springframework.boot.web.servlet.AbstractFilterRegistrationBean的子类,用于注入自定义filter,实现了getFilter方法
org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean#getFilter
public DelegatingFilterProxy getFilter() {
//<4>ServletFilter的实现类 return new DelegatingFilterProxy(this.targetBeanName, this.getWebApplicationContext()) { protected void initFilterBean() throws ServletException { } }; }
<4>
DelegatingFilterProxy就是sevletFilter的实现类
org.springframework.web.filter.DelegatingFilterProxy#doFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { Filter delegateToUse = this.delegate; if (delegateToUse == null) { synchronized(this.delegateMonitor) { delegateToUse = this.delegate; if (delegateToUse == null) { WebApplicationContext wac = this.findWebApplicationContext(); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?"); } //<5>delegate初始化 delegateToUse = this.initDelegate(wac); } this.delegate = delegateToUse; } } // <6>最终是委托给delegate执行的 this.invokeDelegate(delegateToUse, request, response, filterChain); }
<5>
org.springframework.web.filter.DelegatingFilterProxy#initDelegate
protected Filter initDelegate(WebApplicationContext wac) throws ServletException { String targetBeanName = this.getTargetBeanName(); Assert.state(targetBeanName != null, "No target bean name set"); //就是我们的 springSecurityFilterChain Filter delegate = (Filter)wac.getBean(targetBeanName, Filter.class); if (this.isTargetFilterLifecycle()) { delegate.init(this.getFilterConfig()); } return delegate; }
<6>
org.springframework.web.filter.DelegatingFilterProxy#invokeDelegate
protected void invokeDelegate(Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { delegate.doFilter(request, response, filterChain); }