您好,登錄后才能下訂單哦!
這篇文章主要介紹“什么是SpringSecurity過濾器”,在日常操作中,相信很多人在什么是SpringSecurity過濾器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”什么是SpringSecurity過濾器”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
我們知道Spring Security是通過Filter的方式來完成它的核心流程。但是:
Spring Security到底擁有哪些Filter?
這些Filter是如何注入容器?
我們如何自定義自己的Filter?
前面我們已經介紹過了,最開始如果我們要配置Filter,一般是通過web.xml的方式:
<filter> <filter-name>deleFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>spring-bean-name</param-value> </init-param> </filter> <filter-mapping> <filter-name>deleFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
在SpringBoot中可以通過@WebFilter和@ServletComponentScan注解,注入自定義的Filter。
@WebFilter(filterName = "myFilter",urlPatterns = "/*") public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { } @Override public void destroy() { } } @SpringBootApplication @ServletComponentScan(basePackages = "vip.mycollege.filter") public class StartApplication { public static void main(String[] args) { SpringApplication.run(StartApplication.class, args); } }
也可以通過FilterRegistrationBean的方式,注入自定義的Filter。
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new MyFilter()); bean.addUrlPatterns("/*"); return bean; } }
也可以通過DelegatingFilterProxyRegistrationBean的方式。
@Configuration public class FilterConfig { @Bean("proxyFilter") public Filter filter (){ return new Filter() { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { } @Override public void destroy() { } @Bean public DelegatingFilterProxyRegistrationBean delegatingFilterProxyRegistrationBean(){ DelegatingFilterProxyRegistrationBean bean = new DelegatingFilterProxyRegistrationBean("proxyFilter"); bean.addUrlPatterns("/*"); return bean; } }
DelegatingFilterProxyRegistrationBean和FilterRegistrationBean都繼承了AbstractFilterRegistrationBean,從名字上看就知道是一個RegistrationBean,也就是說會在Servlet容器啟動的時候被注入。
DelegatingFilterProxyRegistrationBean會在Servlet容器中注冊一個DelegatingFilterProxy,用來代理Spring IoC容器中某個指定名稱的Filter bean。
SpringBoot有一個SecurityFilterAutoConfiguration的自動配置類,就會配置一個name為springSecurityFilterChain的DelegatingFilterProxyRegistrationBean,這個類的url-pattern默認為/*,也就是說會過濾所有的請求。
name是springSecurityFilterChain是一個什么鬼呢?
答案是:FilterChainProxy。
這個類是在HttpSecurityBeanDefinitionParser的registerFilterChainProxyIfNecessary方法中注冊。
HttpSecurityBeanDefinitionParser也是一個BeanDefinitionParser,因此它會通過parse方法來構建Filter類。
整個流程現在就清晰了:
SpringBoot通過自動配置類搞了個DelegatingFilterProxyRegistrationBean
DelegatingFilterProxyRegistrationBean會在Servlet啟動的時候注冊一個DelegatingFilterProxy
DelegatingFilterProxy會默認會攔截所有的請求,然后交個一個別名為springSecurityFilterChain的FilterChainProxy
FilterChainProxy在持有一個SecurityFilterChain的list
SecurityFilterChain本身又持有一個Filter列表,可以通過match找出url匹配的Request交個filters處理
FilterChainProxy除了持有過濾器,默認內置了一個StrictHttpFirewall一個HTTP防火墻,它采用了嚴格模式,遇到任何可疑的請求,會通過拋出異常RequestRejectedException拒絕該請求。
現在我們知道了Spring Security如何收集利用Filter了。
但是,Spring Security到底背著我們弄了哪些Filter呢?
我只想說很多,要知道有哪些也很簡單,在FilterChainProxy打一個斷點,debug,看一下filterChains變量中的filters列表就能看到有哪些filter
默認情況下filterChains只有一個filte,就是DefaultSecurityFilterChain,看名字就知道這是一個SecurityFilterChain,他包含了一個Filter列表,默認有:
WebAsyncManagerIntegrationFilter:與處理異步請求映射的 WebAsyncManager 進行集成
SecurityContextPersistenceFilter: 請求前保存和請求后清除SecurityContextHolder中的安全上下文
HeaderWriterFilter:將頭信息加入響應中
CsrfFilter:處理跨站請求偽造
LogoutFilter:處理登出
UsernamePasswordAuthenticationFilter:處理基于表單的登錄
DefaultLoginPageGeneratingFilter:如果沒有配置登錄頁,生成默認登錄頁
DefaultLogoutPageGeneratingFilter:如果沒有登出頁,生成默認登出頁
BasicAuthenticationFilter:處理HTTP BASIC認證
RequestCacheAwareFilter:處理請求的緩存
SecurityContextHolderAwareRequestFilter:包裝請求對象request
AnonymousAuthenticationFilter:檢測SecurityContextHolder是否存在Authentication,如不存在提供一個匿名 Authentication
SessionManagementFilter:管理 session 的過濾器
ExceptionTranslationFilter:處理 AccessDeniedException 和 AuthenticationException 異常
FilterSecurityInterceptor: 權限校驗相關
UsernamePasswordAuthenticationFilter本身沒啥好說的,它就是一個Filter,但是因為它用得多,所以說一下。
Filter肯定先看doFilter方法,UsernamePasswordAuthenticationFilter的主要認證邏輯在attemptAuthentication:
@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (this.postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); username = (username != null) ? username : ""; username = username.trim(); String password = obtainPassword(request); password = (password != null) ? password : ""; UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); }
很簡單,就是從request中獲取username和password的字段,封裝成UsernamePasswordAuthenticationToken,然后扔給AuthenticationManager去執行認證,當然,最終認證邏輯肯定是像DaoAuthenticationProvider 這樣的AuthenticationProvider執行。
FilterSecurityInterceptor主要是用來做權限校驗的,具體的鑒權邏輯主要在AbstractSecurityInterceptor中。
FilterSecurityInterceptor也是一個Filter,所以,還是先看doFilter方法,調用了invoke:
public void invoke(FilterInvocation filterInvocation) throws IOException, ServletException { //一次請求中避免重復檢查 if (isApplied(filterInvocation) && this.observeOncePerRequest) { filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse()); return; } // 第一次調用,先設置標記,避免重復調用 if (filterInvocation.getRequest() != null && this.observeOncePerRequest) { filterInvocation.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE); } // 業務邏輯調用之前,執行檢查鑒權操作主要就是在這里面完成 InterceptorStatusToken token = super.beforeInvocation(filterInvocation); try { // 執行具體的業務邏輯 filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse()); } finally { super.finallyInvocation(token); } // 業務邏輯調用之后,主要是處理返回結果 super.afterInvocation(token, null); }
FilterInvocation就是FilterInvocation、ServletResponse、FilterChain的簡單封裝。
我們看到整個invoke的邏輯非常清晰,很像AOP的around結構。
ExceptionTranslationFilter的邏輯有點奇怪,它主要是為了處理 AccessDeniedException 和 AuthenticationException 異常。但是并不是處理它前面產生的異常,而是它后面的Filter產生的異常,因為它前面Filter如果異常了根本到不了它這里。
它后面,默認就只有FilterSecurityInterceptor了,主要會產生AccessDeniedException授權異常,AuthenticationException是因為有一個再認證的過程。
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
ChannelProcessingFilter
ConcurrentSessionFilter
HeaderWriterFilter
CorsFilter
CsrfFilter
LogoutFilter
OAuth3AuthorizationRequestRedirectFilter
Saml2WebSsoAuthenticationRequestFilter
X509AuthenticationFilter
AbstractPreAuthenticatedProcessingFilter
CasAuthenticationFilter
OAuth3LoginAuthenticationFilter
Saml2WebSsoAuthenticationFilter
UsernamePasswordAuthenticationFilter
ConcurrentSessionFilter
OpenIDAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
DigestAuthenticationFilter
BearerTokenAuthenticationFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
JaasApiIntegrationFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
OAuth3AuthorizationCodeGrantFilter
SessionManagementFilter
ExceptionTranslationFilter
SwitchUserFilter
FilterSecurityInterceptor
到此,關于“什么是SpringSecurity過濾器”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。