Spring Boot ,Spring Security的Filter在Tomcat正常,部署在Weblogic 12c Filter顺序出错,导致拦截权限问题

时间:2021-03-19 21:38:48

Spring Boot使用main函数启动或在tomcat中启动时,Filter是按照正常的顺序执行拦截,将工程打包为war包,部署到weblogic上时,Filter执行顺序错乱,导致权限拦截出错。

最近公司的一个项目使用Spring Boot开发,前期也做了技术评估,打包成war到Tomcat和Weblogic 12c上运行,静态资源和RequestMapping访问均正常,以为万事大吉,就开干了,由于Spring Boot提供了main方式启动,开发效率确实提高不少,所以团队都使用这种方式开发,最近项目做的差不多了,要求测试,将工程打包为war包,部署到weblogic上,问题来了,授权的url始终被一个拦截器优先拦截导致授权通不过,将war包放到Tomcat中,运行正常,百思不得其解。

抓捕问题步骤:

将出问题的Filter(我这里为MyFilterSecurityInterceptor)不addFilter到Spring Security的HttpSecurity中,打包部署到weblogic上,问题依旧,查看log日志,还是进入到MyFilterSecurityInterceptor,oh my god.

于是将 @EnableWebSecurity(debug=true) debug打开,发现打印的Log 的 Security filter chain:  [] 确实没有MyFilterSecurityInterceptor,可是为啥还是进入到此MyFilterSecurityInterceptor,当时也没多想,以为weblogic的bug,上百度,google 查看了下,说需要重写SpringBootServletInitializer的onStartup(ServletContext servletContext) ,查看了 SpringBootServletInitializer的方法,也不知道从何写起,于是在源码中打断点追踪代码,发现只要是 实现了 Filter的类 ,并且 @Component 注解的,都进入 org.springframework.boot.web.servlet.AbstractFilterRegistrationBean.onStartup(ServletContext) 方法,被 FilterRegistration.Dynamic added = servletContext.addFilter(name, filter); addFilter添加到 servletContext中,难道系统对Filter的Bean默认注册么,经过搜索,果然是默认Filter自动注册,spring boot官方文档说明默认情况下对 @WebServlet@WebFilter, and @WebListener 以及 @Bean,@Component 这些只要是implements Filter的类,自动添加,默认的过滤路径为 /* 。


更改方式,

去掉 @Component

        MyFilterSecurityInterceptor myFilterSecurityInterceptor = new MyFilterSecurityInterceptor();
        myFilterSecurityInterceptor.setAccessDecisionManager(myAccessDecisionManager);
        myFilterSecurityInterceptor.setSecurityMetadataSource(securityMetadataSourceService);
        httpSecurity
        //添加JWT filter
        .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
        //添加 拦截权限 filter
        .addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);

通过new 方式,即可解决此问题。


其他解决方式:Spring Boot对Servlet,Filter提供了相应的注册类,可以使用 FilterRegistrationBean 来讲进行Filter的精细化配置:

官方给出示例:

@Bean
public FilterRegistrationBean registration(MyFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

看来真是得好好看官方文档啊,不了解Spring Boot,还真是很容易入坑。

将此问题记下,以免再次犯错误。


参考资料:

Spring Boot Document

Spring Boot: 取消Filter自动注册