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);
    }

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章