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,还真是很容易入坑。
将此问题记下,以免再次犯错误。
参考资料: