绕过Spring安全过滤器链

时间:2016-01-29 12:10:41

标签: java spring spring-security

我创建了一个自定义的Spring安全过滤器链,我希望排除以" / health"开头的所有URL。

这是我的过滤器配置:

@Override
public void configure(WebSecurity web) throws Exception {
    web
            .ignoring()
            .antMatchers("/health");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .exceptionHandling()
            .authenticationEntryPoint(ssoEntryPoint());
    http
            .authorizeRequests()

            .antMatchers("/images/**").permitAll()
            .antMatchers("/scripts/**").permitAll()
            .antMatchers("/styles/**").permitAll()
            .antMatchers("/vendor/**").permitAll()
            .antMatchers("/views/**").permitAll()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/api/**").authenticated();

    http    // login configuration
            .addFilterAfter(ssoSpringSecurityFilter(), BasicAuthenticationFilter.class);

    http    //logout configuration
            .logout()
            .logoutSuccessHandler(logoutHandler());

    http.csrf().disable();

}

当我开始申请时,我有这样的痕迹:

  2016-01-29 12:59:23.729  INFO 10572 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/health'], []
  2016-01-29 12:59:23.814 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/images/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/modules/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/scripts/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/styles/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/vendor/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/views/**']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'permitAll', for Ant [pattern='/index.html']
  2016-01-29 12:59:23.816 DEBUG 10572 --- [ost-startStop-1] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'authenticated', for Ant [pattern='/api/**']

当我调用我的服务时,我的这个网址:

  https://localhost:9999/health

我有这个堆栈跟踪:

  2016-01-29 13:05:34.076  INFO 10572 --- [nio-9999-exec-4] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
  2016-01-29 13:05:34.076  INFO 10572 --- [nio-9999-exec-4] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
  2016-01-29 13:05:34.121  INFO 10572 --- [nio-9999-exec-4] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 45 ms
  2016-01-29 13:05:34.136 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/css/**'
  2016-01-29 13:05:34.136 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/js/**'
  2016-01-29 13:05:34.136 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/images/**'
  2016-01-29 13:05:34.137 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/**/favicon.ico'
  2016-01-29 13:05:34.137 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/error'
  2016-01-29 13:05:34.137 DEBUG 10572 --- [nio-9999-exec-4] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/health'; against '/health'
  2016-01-29 13:05:34.137 DEBUG 10572 --- [nio-9999-exec-4] o.s.security.web.FilterChainProxy        : /health has an empty filter list

什么是平均健康状况有一个空的过滤列表?

2 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,我无法让“web.ignoring()。antMatchers(...)”工作。无论如何,我的自定义过滤器都会被调用。

有一种方法可以强制过滤器不影响给定的URL。我找到了这个答案: https://stackoverflow.com/a/19985323/7206367 这提供了一个可能的解决方案,旨在允许特定于筛选器的排除,但它也可用于强制URL排除覆盖。以下是我对这个问题的改编。

以下是支持方法的实现,但是您只需将其添加到HttpSecurity而不是自定义过滤器:

new DelegateRequestMatchingFilter(SECURITY_EXCLUSION_MATCHER, myCustomFilter);

支持代码:

@Configuration
@EnableWebSecurity
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    ...

    private static final RequestMatcher SECURITY_EXCLUSION_MATCHER;
    static {
        String[] urls = new String[] {
                "/login",
                "/refreshToken",
                "/health",
                "/ping"
        };

        //Build Matcher List
        LinkedList<RequestMatcher> matcherList = new LinkedList<>();
        for (String url : urls) {
            matcherList.add(new AntPathRequestMatcher(url));
        }

        //Link Matchers in "OR" config.
        SECURITY_EXCLUSION_MATCHER = new OrRequestMatcher(matcherList);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().requestMatchers(SECURITY_EXCLUSION_MATCHER);
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .requestMatchers(SECURITY_EXCLUSION_MATCHER).permitAll()

    }

    ...

    /**
     * Since the "web.ignoring()..." is not stopping the Custom Filter from acting on the ignored urls,
     * this delegation class will force a check on the Security Exclusion list before allowing the
     * Custom Filter to process anything. 
     */
    public static class DelegateRequestMatchingFilter implements Filter {
        private Filter delegate;
        private RequestMatcher ignoredRequests;

        public DelegateRequestMatchingFilter(RequestMatcher matcher, Filter delegate) {
            this.ignoredRequests = matcher;
            this.delegate = delegate;
        }

        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            if(ignoredRequests.matches(request)) {
                chain.doFilter(req,resp);
            } else {
                delegate.doFilter(req,resp,chain);
            }
        }

        public void init(FilterConfig filterConfig) throws ServletException {
            delegate.init(filterConfig);
        }

        public void destroy() {
            delegate.destroy();
        }
    }
}

或者

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * <p>
 * This matcher will return all matches which match <cdoe>baselineMatches</code>, if
 * and only if, those matches are not matched by <code>ignoreMatches</code>.
 * </p>
 * 
 * <p>
 * This matcher first checks <code>ignoreMatches</code>. If a given request is found
 * as a match to <code>ignoreMatches</code>, this matcher will return false (not a match).
 * If a given request does not match <code>ignoreMatches</code>, then this matcher returns
 * whether or not that request matches <code>baselineMatches</code>.
 * </p>
 * 
 * Effectively:<br>
 * <code>
 * if (ignoreMatches.matches(request)) {
 *      return false;
 * } else {
 *      return baselineMatches.matches(request);
 * }
 * </code>
 * @param baselineMatches Matcher used to determine a request match.
 * @param ignoreMatches Matcher used to exclude matches from the baselineMatcher.
 */
public class AExceptBRequestMatcher implements RequestMatcher {
    private RequestMatcher baselineMatches;
    private RequestMatcher ignoreMatches;

    public AExceptBRequestMatcher(String baselineMatches, RequestMatcher ignoreMatches) {
        this(new AntPathRequestMatcher(baselineMatches), ignoreMatches);
    }

    public AExceptBRequestMatcher(RequestMatcher baselineMatches, RequestMatcher ignoreMatches) {
        this.baselineMatches = baselineMatches;
        this.ignoreMatches = ignoreMatches;
    }

    @Override
    public boolean matches(HttpServletRequest request) {
        if (ignoreMatches.matches(request)) {
            return false;
        } else {
            return baselineMatches.matches(request);
        }
    }
}

然后,在你的过滤器构造函数中调用类似的东西:

public MyCustomFilter() {
    super("/**");
}

相反,您可以接收一个RequestMatcher,匹配您想要忽略/排除的任何内容(例如:第一个示例中的SECURITY_EXCLUSION_MATCHER),并执行以下操作:

public MyCustomFilter(RequestMatcher excludeMatcher) {
    super(new AExceptBRequestMatcher("/**", excludeMatcher));
}

答案 1 :(得分:1)

当你这样做时:

web.ignoring().antMatchers("/health");

与spring配置xml security="none"相同。

这意味着此网址不会受到保护,并且返回一个空的过滤器列表意味着spring不会发送请求,因为没有过滤器,因此会抛出过滤器。意思是不安全的网址

编辑:我不确定什么是差异,但这肯定有用:

http.antMatchers("/health").permitAll();

这应该是.ignoring(),而应该放在HttpSecurity方法下,其余的都是