溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

什么是SpringSecurity過濾器

發(fā)布時(shí)間:2021-10-12 09:21:41 來(lái)源:億速云 閱讀:111 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“什么是SpringSecurity過濾器”,在日常操作中,相信很多人在什么是SpringSecurity過濾器問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”什么是SpringSecurity過濾器”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

前置知識(shí)

我們知道Spring Security是通過Filter的方式來(lái)完成它的核心流程。但是:

  1. Spring Security到底擁有哪些Filter?

  2. 這些Filter是如何注入容器?

  3. 我們?nèi)绾巫远x自己的Filter?

web.xml配置

前面我們已經(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中添加Filter

在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。

FilterChainProxy

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)在就清晰了:

  1. SpringBoot通過自動(dòng)配置類搞了個(gè)DelegatingFilterProxyRegistrationBean

  2. DelegatingFilterProxyRegistrationBean會(huì)在Servlet啟動(dòng)的時(shí)候注冊(cè)一個(gè)DelegatingFilterProxy

  3. DelegatingFilterProxy會(huì)默認(rèn)會(huì)攔截所有的請(qǐng)求,然后交個(gè)一個(gè)別名為springSecurityFilterChain的FilterChainProxy

  4. FilterChainProxy在持有一個(gè)SecurityFilterChain的list

  5. 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)有:

  1. WebAsyncManagerIntegrationFilter:與處理異步請(qǐng)求映射的 WebAsyncManager 進(jìn)行集成

  2. SecurityContextPersistenceFilter: 請(qǐng)求前保存和請(qǐng)求后清除SecurityContextHolder中的安全上下文

  3. HeaderWriterFilter:將頭信息加入響應(yīng)中

  4. CsrfFilter:處理跨站請(qǐng)求偽造

  5. LogoutFilter:處理登出

  6. UsernamePasswordAuthenticationFilter:處理基于表單的登錄

  7. DefaultLoginPageGeneratingFilter:如果沒有配置登錄頁(yè),生成默認(rèn)登錄頁(yè)

  8. DefaultLogoutPageGeneratingFilter:如果沒有登出頁(yè),生成默認(rèn)登出頁(yè)

  9. BasicAuthenticationFilter:處理HTTP BASIC認(rèn)證

  10. RequestCacheAwareFilter:處理請(qǐng)求的緩存

  11. SecurityContextHolderAwareRequestFilter:包裝請(qǐng)求對(duì)象request

  12. AnonymousAuthenticationFilter:檢測(cè)SecurityContextHolder是否存在Authentication,如不存在提供一個(gè)匿名 Authentication

  13. SessionManagementFilter:管理 session 的過濾器

  14. ExceptionTranslationFilter:處理 AccessDeniedException 和 AuthenticationException 異常

  15. FilterSecurityInterceptor: 權(quán)限校驗(yàn)相關(guān)

重要Filter

UsernamePasswordAuthenticationFilter

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

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

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í)用的文章!

向AI問一下細(xì)節(jié)

免責(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)容。

AI