您好,登录后才能下订单哦!
这篇文章主要介绍“什么是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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。