什么是SpringSecurity过滤器

发布时间:2021-10-12 09:21:41 作者:iii
来源:亿速云 阅读:120

这篇文章主要介绍“什么是SpringSecurity过滤器”,在日常操作中,相信很多人在什么是SpringSecurity过滤器问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是SpringSecurity过滤器”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前置知识

我们知道Spring Security是通过Filter的方式来完成它的核心流程。但是:

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

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

  3. 我们如何自定义自己的Filter?

web.xml配置

前面我们已经介绍过了,最开始如果我们要配置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,从名字上看就知道是一个RegistrationBean,也就是说会在Servlet容器启动的时候被注入。

DelegatingFilterProxyRegistrationBean会在Servlet容器中注册一个DelegatingFilterProxy,用来代理Spring IoC容器中某个指定名称的Filter bean。

FilterChainProxy

SpringBoot有一个SecurityFilterAutoConfiguration的自动配置类,就会配置一个name为springSecurityFilterChain的DelegatingFilterProxyRegistrationBean,这个类的url-pattern默认为/*,也就是说会过滤所有的请求。

name是springSecurityFilterChain是一个什么鬼呢?

答案是:FilterChainProxy。

这个类是在HttpSecurityBeanDefinitionParser的registerFilterChainProxyIfNecessary方法中注册。

HttpSecurityBeanDefinitionParser也是一个BeanDefinitionParser,因此它会通过parse方法来构建Filter类。

整个流程现在就清晰了:

  1. SpringBoot通过自动配置类搞了个DelegatingFilterProxyRegistrationBean

  2. DelegatingFilterProxyRegistrationBean会在Servlet启动的时候注册一个DelegatingFilterProxy

  3. DelegatingFilterProxy会默认会拦截所有的请求,然后交个一个别名为springSecurityFilterChain的FilterChainProxy

  4. FilterChainProxy在持有一个SecurityFilterChain的list

  5. 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列表,默认有:

  1. WebAsyncManagerIntegrationFilter:与处理异步请求映射的 WebAsyncManager 进行集成

  2. SecurityContextPersistenceFilter: 请求前保存和请求后清除SecurityContextHolder中的安全上下文

  3. HeaderWriterFilter:将头信息加入响应中

  4. CsrfFilter:处理跨站请求伪造

  5. LogoutFilter:处理登出

  6. UsernamePasswordAuthenticationFilter:处理基于表单的登录

  7. DefaultLoginPageGeneratingFilter:如果没有配置登录页,生成默认登录页

  8. DefaultLogoutPageGeneratingFilter:如果没有登出页,生成默认登出页

  9. BasicAuthenticationFilter:处理HTTP BASIC认证

  10. RequestCacheAwareFilter:处理请求的缓存

  11. SecurityContextHolderAwareRequestFilter:包装请求对象request

  12. AnonymousAuthenticationFilter:检测SecurityContextHolder是否存在Authentication,如不存在提供一个匿名 Authentication

  13. SessionManagementFilter:管理 session 的过滤器

  14. ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常

  15. FilterSecurityInterceptor: 权限校验相关

重要Filter

UsernamePasswordAuthenticationFilter

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

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

ExceptionTranslationFilter的逻辑有点奇怪,它主要是为了处理 AccessDeniedException 和 AuthenticationException 异常。但是并不是处理它前面产生的异常,而是它后面的Filter产生的异常,因为它前面Filter如果异常了根本到不了它这里。

它后面,默认就只有FilterSecurityInterceptor了,主要会产生AccessDeniedException授权异常,AuthenticationException是因为有一个再认证的过程。

过滤器

到此,关于“什么是SpringSecurity过滤器”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. SpringSecurity 测试实战
  2. 怎么在SpringSecurity中自定义过滤器

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springsecurity

上一篇:CreateWeb.vbs有什么用

下一篇:如何理解SpringSecurity原理认证

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》