Spring|Spring Security之默认的过滤器链及自定义Filter操作
Spring Security 过滤器链及自定义Filter
别名 | 类名称 | Namespace Element or Attribute |
---|---|---|
CHANNEL_FILTER | ChannelProcessingFilter | http/intercept-url@requires-channel |
SECURITY_CONTEXT_FILTER | SecurityContextPersistenceFilter | http |
CONCURRENT_SESSION_FILTER | ConcurrentSessionFilter | session-management/concurrency-control |
HEADERS_FILTER | HeaderWriterFilter | http/headers |
CSRF_FILTER | CsrfFilter | http/csrf |
LOGOUT_FILTER | LogoutFilter | http/logout |
X509_FILTER | X509AuthenticationFilter | http/x509 |
PRE_AUTH_FILTER | AbstractPreAuthenticatedProcessingFilter( Subclasses) | N/A |
CAS_FILTER | CasAuthenticationFilter | N/A |
FORM_LOGIN_FILTER | UsernamePasswordAuthenticationFilter | http/form-login |
BASIC_AUTH_FILTER | BasicAuthenticationFilter | http/http-basic |
SERVLET_API_SUPPORT_FILTER | SecurityContextHolderAwareRequestFilter | http/@servlet-api-provision |
JAAS_API_SUPPORT_FILTER | JaasApiIntegrationFilter | http/@jaas-api-provision |
REMEMBER_ME_FILTER | RememberMeAuthenticationFilter | http/remember-me |
ANONYMOUS_FILTER | AnonymousAuthenticationFilter | http/anonymous |
SESSION_MANAGEMENT_FILTER | SessionManagementFilter | session-management |
EXCEPTION_TRANSLATION_FILTER | ExceptionTranslationFilter | http |
FILTER_SECURITY_INTERCEPTOR | FilterSecurityInterceptor | http |
SWITCH_USER_FILTER | SwitchUserFilter | N/A |
自定义 Filter
自定义的 Filter 建议继承 GenericFilterBean,本文示例:
package com.example.filter; import org.springframework.web.filter.GenericFilterBean; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; /** * @author 咸鱼 * @date 2019-05-26 18:02 */public class BeforeLoginFilter extends GenericFilterBean {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("在 UsernamePasswordAuthenticationFilter 前调用"); chain.doFilter(request, response); }}
配置自定义 Filter 在 Spring Security 过滤器链中的位置
配置很简单,本文示例:
@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/user/**").hasAuthority("USER").and().formLogin().loginPage("/login").defaultSuccessUrl("/user").and().logout().logoutUrl("/logout").logoutSuccessUrl("/login"); // 在 UsernamePasswordAuthenticationFilter 前添加 BeforeLoginFilterhttp.addFilterBefore(new BeforeLoginFilter(), UsernamePasswordAuthenticationFilter.class); // 在 CsrfFilter 后添加 AfterCsrfFilterhttp.addFilterAfter(new AfterCsrfFilter(), CsrfFilter.class); }
说明:
HttpSecurity 有三个常用方法来配置:
addFilterBefore(Filter filter, Class extends Filter> beforeFilter)
在 beforeFilter 之前添加 filter
addFilterAfter(Filter filter, Class extends Filter> afterFilter)
在 afterFilter 之后添加 filter
addFilterAt(Filter filter, Class extends Filter> atFilter)
在 atFilter 相同位置添加 filter, 此 filter 不覆盖 filter
通过在不同 Filter 的 doFilter() 方法中加断点调试,可以判断哪个 filter 先执行,从而判断 filter 的执行顺序 。
spring security添加自定义过滤器 1、定义自己的过滤器
2、指定位置,通过HttpSecurity的方法指定
定义过滤器
package com.qiudaozhang.springsecurity.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class RequestHeadCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest; var httpResponse = (HttpServletResponse) servletResponse; String requestId = httpRequest.getHeader("Request-id"); if(requestId == null || requestId.isBlank()) {httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); return; }filterChain.doFilter(servletRequest,servletResponse); }}
package com.qiudaozhang.springsecurity.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class RequestParamCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest; var httpResponse = (HttpServletResponse) servletResponse; String timestamp = httpRequest.getParameter("timestamp"); if(timestamp == null || timestamp.isBlank()) {httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); return; }filterChain.doFilter(servletRequest,servletResponse); }}
指定位置
HttpSecurity中有两个方法,指定过滤器的位置,一个指定在谁前面,一个指定在谁后面。
public HttpSecurity addFilterAfter(Filter filter, Class extends Filter> afterFilter) {this.comparator.registerAfter(filter.getClass(), afterFilter); return this.addFilter(filter); }public HttpSecurity addFilterBefore(Filter filter, Class extends Filter> beforeFilter) {this.comparator.registerBefore(filter.getClass(), beforeFilter); return this.addFilter(filter); }
package com.qiudaozhang.springsecurity.config; import com.qiudaozhang.springsecurity.filter.RequestHeadCheckFilter; import com.qiudaozhang.springsecurity.filter.RequestParamCheckFilter; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @Configurationpublic class ProjectConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(new RequestHeadCheckFilter(),BasicAuthenticationFilter.class).addFilterAfter(new RequestParamCheckFilter(),BasicAuthenticationFilter.class).authorizeRequests().anyRequest().permitAll(); }}
测试
准备一个端点测试
package com.qiudaozhang.springsecurity.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class HelloController {@GetMapping("hello")public String hello () {return "hello"; }}
文章图片
当前没有传递timestamp参数,所以参照约定,过滤器直接给出403.
文章图片
当前头部信息和参数信息都提供了,检测通过。
实际应用场景 检测相关的头部,参数等等信息日志过滤器,将所有请求的相关数据记录下来特殊的权限校验等等。
【Spring|Spring Security之默认的过滤器链及自定义Filter操作】以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- Activiti(一)SpringBoot2集成Activiti6
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天