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,還真是很容易入坑。
將此問題記下,以免再次犯錯誤。
參考資料: