Spring Security配置过滤器为何如此复杂?

2026-05-25 12:201阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计940个文字,预计阅读时间需要4分钟。

Spring Security配置过滤器为何如此复杂?

以前胖哥带大家用Spring Security过滤器实现了验证码认证,今天我们来改进一下验证码认证的配置方式,使其更符合Spring Security的设计风格,并增加内嵌的过滤器。使用`CaptchaAuthenticationFilter`。

以前胖哥带大家用Spring Security过滤器实现了验证码认证,今天我们来改良一下验证码认证的配置方式,更符合Spring Security的设计风格,也更加内卷。

CaptchaAuthenticationFilter是通过模仿UsernamePasswordAuthenticationFilter实现的。同样的道理,由于UsernamePasswordAuthenticationFilter的配置是由FormLoginConfigurer来完成的,应该也能模仿一下FormLoginConfigurer,写一个配置类CaptchaAuthenticationFilterConfigurer去配置CaptchaAuthenticationFilter

Spring Security配置过滤器为何如此复杂?

public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> { // 省略 } AbstractAuthenticationFilterConfigurer

FormLoginConfigurer看起来有点复杂,不过继承关系并不复杂,只继承了AbstractAuthenticationFilterConfigurer

public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter> extends AbstractHttpConfigurer<T, B> { }

理论上我们模仿一下,也继承一下这个类,但是你会发现这种方式行不通。因为AbstractAuthenticationFilterConfigurer只能Spring Security内部使用,不建议自定义。原因在于它最终向HttpSecurity添加过滤器使用的是HttpSecurity.addFilter(Filter)方法,这个方法只有内置过滤器(参见FilterOrderRegistration)才能使用。了解了这个机制之后,我们只能往上再抽象一层,去改造其父类AbstractHttpConfigurer

改造过程

AbstractAuthenticationFilterConfigurer<B,T,F>中的B是实际指的HttpSecurity,因此这个要保留;

T指的是它本身的实现,我们配置CaptchaAuthenticationFilter不需要下沉一层到FormLoginConfigurer这个继承级别,直接在AbstractAuthenticationFilterConfigurer这个继承级别实现即可,因此T这里指的就是需要配置类本身,也不需要再抽象化,因此是不需要的;同样的原因F也不需要,很明确是CaptchaAuthenticationFilter,不需要再泛化。这样CaptchaAuthenticationFilter的配置类结构可以这样定义:

public class CaptchaAuthenticationFilterConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<CaptchaAuthenticationFilterConfigurer<H>, H> { // 不再泛化 具体化 private final CaptchaAuthenticationFilter authFilter; // 特定的验证码用户服务 private CaptchaUserDetailsService captchaUserDetailsService; // 验证码处理服务 private CaptchaService captchaService; // 保存认证请求细节的策略 private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource; // 默认使用保存请求认证成功处理器 private SavedRequestAwareAuthenticationSuccessHandler defaultSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler(); // 认证成功处理器 private AuthenticationSuccessHandler successHandler = this.defaultSuccessHandler; // 登录认证端点 private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; // 是否 自定义页面 private boolean customLoginPage; // 登录页面 private String loginPage; // 登录成功url private String loginProcessingUrl; // 认证失败处理器 private AuthenticationFailureHandler failureHandler; // 认证路径是否放开 private boolean permitAll; // 认证失败的url private String failureUrl; /** * Creates a new instance with minimal defaults */ public CaptchaAuthenticationFilterConfigurer() { setLoginPage("/login/captcha"); this.authFilter = new CaptchaAuthenticationFilter(); } public CaptchaAuthenticationFilterConfigurer<H> formLoginDisabled() { this.formLoginEnabled = false; return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaUserDetailsService(CaptchaUserDetailsService captchaUserDetailsService) { this.captchaUserDetailsService = captchaUserDetailsService; return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaService(CaptchaService captchaService) { this.captchaService = captchaService; return this; } public CaptchaAuthenticationFilterConfigurer<H> usernameParameter(String usernameParameter) { authFilter.setUsernameParameter(usernameParameter); return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaParameter(String captchaParameter) { authFilter.setCaptchaParameter(captchaParameter); return this; } public CaptchaAuthenticationFilterConfigurer<H> parametersConverter(Converter<HttpServletRequest, CaptchaAuthenticationToken> converter) { authFilter.setConverter(converter); return this; } @Override public void init(H felord.cn

博主:码农小胖哥
出处:felord.cn
本文版权归原作者所有,不可商用,转载需要声明出处,否则保留追究法律责任的权利。如果文中有什么错误,欢迎指出。以免更多的人被误导。

本文共计940个文字,预计阅读时间需要4分钟。

Spring Security配置过滤器为何如此复杂?

以前胖哥带大家用Spring Security过滤器实现了验证码认证,今天我们来改进一下验证码认证的配置方式,使其更符合Spring Security的设计风格,并增加内嵌的过滤器。使用`CaptchaAuthenticationFilter`。

以前胖哥带大家用Spring Security过滤器实现了验证码认证,今天我们来改良一下验证码认证的配置方式,更符合Spring Security的设计风格,也更加内卷。

CaptchaAuthenticationFilter是通过模仿UsernamePasswordAuthenticationFilter实现的。同样的道理,由于UsernamePasswordAuthenticationFilter的配置是由FormLoginConfigurer来完成的,应该也能模仿一下FormLoginConfigurer,写一个配置类CaptchaAuthenticationFilterConfigurer去配置CaptchaAuthenticationFilter

Spring Security配置过滤器为何如此复杂?

public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> { // 省略 } AbstractAuthenticationFilterConfigurer

FormLoginConfigurer看起来有点复杂,不过继承关系并不复杂,只继承了AbstractAuthenticationFilterConfigurer

public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter> extends AbstractHttpConfigurer<T, B> { }

理论上我们模仿一下,也继承一下这个类,但是你会发现这种方式行不通。因为AbstractAuthenticationFilterConfigurer只能Spring Security内部使用,不建议自定义。原因在于它最终向HttpSecurity添加过滤器使用的是HttpSecurity.addFilter(Filter)方法,这个方法只有内置过滤器(参见FilterOrderRegistration)才能使用。了解了这个机制之后,我们只能往上再抽象一层,去改造其父类AbstractHttpConfigurer

改造过程

AbstractAuthenticationFilterConfigurer<B,T,F>中的B是实际指的HttpSecurity,因此这个要保留;

T指的是它本身的实现,我们配置CaptchaAuthenticationFilter不需要下沉一层到FormLoginConfigurer这个继承级别,直接在AbstractAuthenticationFilterConfigurer这个继承级别实现即可,因此T这里指的就是需要配置类本身,也不需要再抽象化,因此是不需要的;同样的原因F也不需要,很明确是CaptchaAuthenticationFilter,不需要再泛化。这样CaptchaAuthenticationFilter的配置类结构可以这样定义:

public class CaptchaAuthenticationFilterConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<CaptchaAuthenticationFilterConfigurer<H>, H> { // 不再泛化 具体化 private final CaptchaAuthenticationFilter authFilter; // 特定的验证码用户服务 private CaptchaUserDetailsService captchaUserDetailsService; // 验证码处理服务 private CaptchaService captchaService; // 保存认证请求细节的策略 private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource; // 默认使用保存请求认证成功处理器 private SavedRequestAwareAuthenticationSuccessHandler defaultSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler(); // 认证成功处理器 private AuthenticationSuccessHandler successHandler = this.defaultSuccessHandler; // 登录认证端点 private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; // 是否 自定义页面 private boolean customLoginPage; // 登录页面 private String loginPage; // 登录成功url private String loginProcessingUrl; // 认证失败处理器 private AuthenticationFailureHandler failureHandler; // 认证路径是否放开 private boolean permitAll; // 认证失败的url private String failureUrl; /** * Creates a new instance with minimal defaults */ public CaptchaAuthenticationFilterConfigurer() { setLoginPage("/login/captcha"); this.authFilter = new CaptchaAuthenticationFilter(); } public CaptchaAuthenticationFilterConfigurer<H> formLoginDisabled() { this.formLoginEnabled = false; return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaUserDetailsService(CaptchaUserDetailsService captchaUserDetailsService) { this.captchaUserDetailsService = captchaUserDetailsService; return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaService(CaptchaService captchaService) { this.captchaService = captchaService; return this; } public CaptchaAuthenticationFilterConfigurer<H> usernameParameter(String usernameParameter) { authFilter.setUsernameParameter(usernameParameter); return this; } public CaptchaAuthenticationFilterConfigurer<H> captchaParameter(String captchaParameter) { authFilter.setCaptchaParameter(captchaParameter); return this; } public CaptchaAuthenticationFilterConfigurer<H> parametersConverter(Converter<HttpServletRequest, CaptchaAuthenticationToken> converter) { authFilter.setConverter(converter); return this; } @Override public void init(H felord.cn

博主:码农小胖哥
出处:felord.cn
本文版权归原作者所有,不可商用,转载需要声明出处,否则保留追究法律责任的权利。如果文中有什么错误,欢迎指出。以免更多的人被误导。