security第九集 自定义过滤器

📅 2026/6/18 18:13:59
security第九集 自定义过滤器
Spring Security中的过滤器架构是基于Servlet构建的因此下面先回顾Servlet中的过滤器。publicinterfaceFilter{defaultvoidinit(FilterConfigfilterConfig)throwsServletException{}voiddoFilter(ServletRequestvar1,ServletResponsevar2,FilterChainvar3)throwsIOException,ServletException;defaultvoiddestroy(){}}当应用程序启动时Servlet容器会调用init()方法。该方法只会调用一次所以该方法中应该包含初始化该过滤器的相关代码。对应地destroy()方法用于释放该过滤器所占有的资源。一个过滤器组件所包含的业务逻辑应该位于doFilter()方法中该方法带有三个参数分别是ServletRequest、ServletResponse和FilterChain。这三个参数都很重要具体说明如下。ServletRequest表示HTTP请求使用该对象获取与请求相关的详细信息。ServletResponse表示HTTP 响应使用该对象构建响应结果然后将其发送回客户端或沿着过滤器链向后传递。FilterChain表示过滤器链使用该对象将请求转发到过滤器链中的下一个过滤器。下面我们基于servlet过滤器编写 Spring Security 中的自定义过滤器,来实现如下功能在请求中要检验header中 是否存在 flag 标志存在就进行下一步用户认证不存在就返回错误码在用户认证成功后用日志打印出flag的值。首先我们创建第一个过滤器 RequestCheckerFilter 来实现 前三个步骤importcom.alibaba.druid.util.StringUtils;importjavax.servlet.*;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;publicclassRequestCheckerFilterimplementsFilter{Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{Filter.super.init(filterConfig);}Overridepublicvoiddestroy(){Filter.super.destroy();}OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequesthttpServletRequest(HttpServletRequest)servletRequest;HttpServletResponsehttpServletResponse(HttpServletResponse)servletResponse;//从header中获取flag的值StringflaghttpServletRequest.getHeader(flag);//判断flag的值 是否存在if(StringUtils.isEmpty(flag)){//随便返回一个错误码httpServletResponse.setStatus(HttpServletResponse.SC_BAD_GATEWAY);return;}//将请求转发到过滤器链中的下一个过滤器filterChain.doFilter(servletRequest,servletResponse);}}接下来创建第二个过滤器LoggingFilter来实现打印flag的值importjavax.servlet.*;importjavax.servlet.http.HttpServletRequest;importjava.io.IOException;importjava.util.logging.Logger;publicclassLoggingFilterimplementsFilter{privatefinalLoggerloggerLogger.getLogger(LoggingFilter.class.getName());Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{Filter.super.init(filterConfig);}Overridepublicvoiddestroy(){Filter.super.destroy();}OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequesthttpServletRequest(HttpServletRequest)servletRequest;//从ServletRequest获取请求数据并记录StringflaghttpServletRequest.getHeader(flag);logger.info(Authtication for:flag);//将请求在过滤器链上继续传递filterChain.doFilter(servletRequest,servletResponse);}}定义好两个过滤器之后怎么将它们整合到Spring Security的过滤器链中并且设置过滤器的顺序。首先我们要知道实现HTTP基础认证机制的过滤器是 BasicAuthenticationFilter那么最合理的顺序就是认证前检验flag标志来排除一批无效请求认证认证成功后打印flag标志所以基于上面的思考做如下配置importcom.kai.oauth.securityservice.filter.LoggingFilter;importcom.kai.oauth.securityservice.filter.RequestCheckerFilter;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.core.userdetails.User;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;importorg.springframework.security.web.authentication.www.BasicAuthenticationFilter;/** * p/p * * author wangkai * date 2024-12-10 16:32 */ConfigurationpublicclassMyWebSecurityConfigAdapterextendsWebSecurityConfigurerAdapter{Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{UserDetailsuserUser.withUsername(user).password({noop}123456).roles(USER).build();auth.inMemoryAuthentication().withUser(user);UserDetailsadminUser.withUsername(admin).password({noop}123456).roles(ADMIN).build();auth.inMemoryAuthentication().withUser(admin);}Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.httpBasic();http.addFilterBefore(newRequestCheckerFilter(),BasicAuthenticationFilter.class).addFilterAfter(newLoggingFilter(),BasicAuthenticationFilter.class).authorizeRequests().anyRequest().authenticated();}}可以看到配置中用了两个方法 addFilterBefore在之前 和 addFilterAfter在之后 来调整过滤器的顺序。接下来 用postman测试一下先测试一个提供用户信息但header中没有flag标志的看status ,是 502 Bad Gateway,这正是在 RequestCheckerFilter中定义的 状态码 HttpServletResponse.SC_BAD_GATEWAY。现在在请求头header中加上 flag 试试观察控制台当用户信息正确的时候 的确输出了 flag的日志到此自定义的过滤器配置已经成功了下面列举一些 Spring Security中的一些常见过滤器ChannelProcessingFilter 可根据配置进行协议的重定向SecurityContextPersistenceFilter针对每个Web请求在结束时将SecurityContext保存到HttpSession中ConcurrentSessionFilter 刷新Session的最后更新时间并判断Session是否过期UsernamePasswordAuthenticationFilter、CasAuthenticationFilter、BasicAuthenticationFilter等Spring Security内置的一组认证过滤器SecurityContextHolderAwareRequestFilter 安全上下文控制过滤器JaasApiIntegrationFilter Jaas相关过滤器RememberMeAuthenticationFilter 提供“Remember Me”功能的过滤器AnonymousAuthenticationFilter 匿名授权过滤器ExceptionTranslationFilter 异常捕获和处理过滤器FilterSecurityInterceptor 权限控制过滤器