您好,登錄后才能下訂單哦!
這篇文章主要介紹“什么是SpringSecurity過濾器”,在日常操作中,相信很多人在什么是SpringSecurity過濾器問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”什么是SpringSecurity過濾器”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
我們知道Spring Security是通過Filter的方式來(lái)完成它的核心流程。但是:
Spring Security到底擁有哪些Filter?
這些Filter是如何注入容器?
我們?nèi)绾巫远x自己的Filter?
前面我們已經(jīng)介紹過了,最開始如果我們要配置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,從名字上看就知道是一個(gè)RegistrationBean,也就是說(shuō)會(huì)在Servlet容器啟動(dòng)的時(shí)候被注入。
DelegatingFilterProxyRegistrationBean會(huì)在Servlet容器中注冊(cè)一個(gè)DelegatingFilterProxy,用來(lái)代理Spring IoC容器中某個(gè)指定名稱的Filter bean。
SpringBoot有一個(gè)SecurityFilterAutoConfiguration的自動(dòng)配置類,就會(huì)配置一個(gè)name為springSecurityFilterChain的DelegatingFilterProxyRegistrationBean,這個(gè)類的url-pattern默認(rèn)為/*,也就是說(shuō)會(huì)過濾所有的請(qǐng)求。
name是springSecurityFilterChain是一個(gè)什么鬼呢?
答案是:FilterChainProxy。
這個(gè)類是在HttpSecurityBeanDefinitionParser的registerFilterChainProxyIfNecessary方法中注冊(cè)。
HttpSecurityBeanDefinitionParser也是一個(gè)BeanDefinitionParser,因此它會(huì)通過parse方法來(lái)構(gòu)建Filter類。
整個(gè)流程現(xiàn)在就清晰了:
SpringBoot通過自動(dòng)配置類搞了個(gè)DelegatingFilterProxyRegistrationBean
DelegatingFilterProxyRegistrationBean會(huì)在Servlet啟動(dòng)的時(shí)候注冊(cè)一個(gè)DelegatingFilterProxy
DelegatingFilterProxy會(huì)默認(rèn)會(huì)攔截所有的請(qǐng)求,然后交個(gè)一個(gè)別名為springSecurityFilterChain的FilterChainProxy
FilterChainProxy在持有一個(gè)SecurityFilterChain的list
SecurityFilterChain本身又持有一個(gè)Filter列表,可以通過match找出url匹配的Request交個(gè)filters處理
FilterChainProxy除了持有過濾器,默認(rèn)內(nèi)置了一個(gè)StrictHttpFirewall一個(gè)HTTP防火墻,它采用了嚴(yán)格模式,遇到任何可疑的請(qǐng)求,會(huì)通過拋出異常RequestRejectedException拒絕該請(qǐng)求。
現(xiàn)在我們知道了Spring Security如何收集利用Filter了。
但是,Spring Security到底背著我們弄了哪些Filter呢?
我只想說(shuō)很多,要知道有哪些也很簡(jiǎn)單,在FilterChainProxy打一個(gè)斷點(diǎn),debug,看一下filterChains變量中的filters列表就能看到有哪些filter
默認(rèn)情況下filterChains只有一個(gè)filte,就是DefaultSecurityFilterChain,看名字就知道這是一個(gè)SecurityFilterChain,他包含了一個(gè)Filter列表,默認(rèn)有:
WebAsyncManagerIntegrationFilter:與處理異步請(qǐng)求映射的 WebAsyncManager 進(jìn)行集成
SecurityContextPersistenceFilter: 請(qǐng)求前保存和請(qǐng)求后清除SecurityContextHolder中的安全上下文
HeaderWriterFilter:將頭信息加入響應(yīng)中
CsrfFilter:處理跨站請(qǐng)求偽造
LogoutFilter:處理登出
UsernamePasswordAuthenticationFilter:處理基于表單的登錄
DefaultLoginPageGeneratingFilter:如果沒有配置登錄頁(yè),生成默認(rèn)登錄頁(yè)
DefaultLogoutPageGeneratingFilter:如果沒有登出頁(yè),生成默認(rèn)登出頁(yè)
BasicAuthenticationFilter:處理HTTP BASIC認(rèn)證
RequestCacheAwareFilter:處理請(qǐng)求的緩存
SecurityContextHolderAwareRequestFilter:包裝請(qǐng)求對(duì)象request
AnonymousAuthenticationFilter:檢測(cè)SecurityContextHolder是否存在Authentication,如不存在提供一個(gè)匿名 Authentication
SessionManagementFilter:管理 session 的過濾器
ExceptionTranslationFilter:處理 AccessDeniedException 和 AuthenticationException 異常
FilterSecurityInterceptor: 權(quán)限校驗(yàn)相關(guān)
UsernamePasswordAuthenticationFilter本身沒啥好說(shuō)的,它就是一個(gè)Filter,但是因?yàn)樗玫枚?,所以說(shuō)一下。
Filter肯定先看doFilter方法,UsernamePasswordAuthenticationFilter的主要認(rèn)證邏輯在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); }
很簡(jiǎn)單,就是從request中獲取username和password的字段,封裝成UsernamePasswordAuthenticationToken,然后扔給AuthenticationManager去執(zhí)行認(rèn)證,當(dāng)然,最終認(rèn)證邏輯肯定是像DaoAuthenticationProvider 這樣的AuthenticationProvider執(zhí)行。
FilterSecurityInterceptor主要是用來(lái)做權(quán)限校驗(yàn)的,具體的鑒權(quán)邏輯主要在AbstractSecurityInterceptor中。
FilterSecurityInterceptor也是一個(gè)Filter,所以,還是先看doFilter方法,調(diào)用了invoke:
public void invoke(FilterInvocation filterInvocation) throws IOException, ServletException { //一次請(qǐng)求中避免重復(fù)檢查 if (isApplied(filterInvocation) && this.observeOncePerRequest) { filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse()); return; } // 第一次調(diào)用,先設(shè)置標(biāo)記,避免重復(fù)調(diào)用 if (filterInvocation.getRequest() != null && this.observeOncePerRequest) { filterInvocation.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE); } // 業(yè)務(wù)邏輯調(diào)用之前,執(zhí)行檢查鑒權(quán)操作主要就是在這里面完成 InterceptorStatusToken token = super.beforeInvocation(filterInvocation); try { // 執(zhí)行具體的業(yè)務(wù)邏輯 filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse()); } finally { super.finallyInvocation(token); } // 業(yè)務(wù)邏輯調(diào)用之后,主要是處理返回結(jié)果 super.afterInvocation(token, null); }
FilterInvocation就是FilterInvocation、ServletResponse、FilterChain的簡(jiǎn)單封裝。
我們看到整個(gè)invoke的邏輯非常清晰,很像AOP的around結(jié)構(gòu)。
ExceptionTranslationFilter的邏輯有點(diǎn)奇怪,它主要是為了處理 AccessDeniedException 和 AuthenticationException 異常。但是并不是處理它前面產(chǎn)生的異常,而是它后面的Filter產(chǎn)生的異常,因?yàn)樗懊鍲ilter如果異常了根本到不了它這里。
它后面,默認(rèn)就只有FilterSecurityInterceptor了,主要會(huì)產(chǎn)生AccessDeniedException授權(quán)異常,AuthenticationException是因?yàn)橛幸粋€(gè)再認(rèn)證的過程。
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
到此,關(guān)于“什么是SpringSecurity過濾器”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。