1. 概述
Spring Security的Java配置支持提供了强大的流式API,用于定义应用程序的安全映射和规则。本文将深入探讨如何更进一步——定义自定义配置器:这是一种高级且灵活的方式,能将自定义逻辑融入标准安全配置中。
我们通过一个简单场景实现这个功能:根据指定的错误状态码列表,为已认证用户记录错误日志。
2. 自定义SecurityConfigurer
要定义自定义配置器,首先需要继承AbstractHttpConfigurer
类:
public class ClientErrorLoggingConfigurer
extends AbstractHttpConfigurer<ClientErrorLoggingConfigurer, HttpSecurity> {
private List<HttpStatus> errorCodes;
// 标准构造方法
@Override
public void init(HttpSecurity http) throws Exception {
// 初始化代码
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(
new ClientErrorLoggingFilter(errorCodes),
FilterSecurityInterceptor.class);
}
}
**核心方法是configure()
**——包含该配置器要应用的安全逻辑。在我们的示例中:
- 在Spring Security最后一个过滤器后注册新过滤器
- 添加
errorCodes
属性控制需记录的错误码
init()
方法(可选)在configure()
前执行,可用于额外配置。
接下来定义过滤器类:
public class ClientErrorLoggingFilter extends GenericFilterBean {
private static final Logger logger = LogManager.getLogger(
ClientErrorLoggingFilter.class);
private List<HttpStatus> errorCodes;
// 标准构造方法
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
//...
chain.doFilter(request, response);
}
}
这是标准Spring过滤器,继承GenericFilterBean
并重写doFilter()
。重点关注其核心逻辑:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
chain.doFilter(request, response);
return;
}
int status = ((HttpServletResponse) response).getStatus();
if (status < 400 || status >= 500) {
chain.doFilter(request, response);
return;
}
if (errorCodes == null) {
logger.debug("User " + auth.getName() + " encountered error " + status);
} else {
if (errorCodes.stream().anyMatch(s -> s.value() == status)) {
logger.debug("User " + auth.getName() + " encountered error " + status);
}
}
执行流程:
- ✅ 获取当前认证信息,未认证则跳过
- ✅ 检查响应状态码(仅处理400-499客户端错误)
- ✅ 根据配置决定是否记录日志:
- 未指定错误码时记录所有客户端错误
- 指定错误码时仅记录匹配的错误
3. 使用自定义配置器
通过两步集成自定义配置器:定义Bean + 使用apply()
方法
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
//...
.and()
.apply(clientErrorLogging());
return http.build();
}
@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
return new ClientErrorLoggingConfigurer();
}
}
也可指定特定错误码:
@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
return new ClientErrorLoggingConfigurer(Arrays.asList(HttpStatus.NOT_FOUND)) ;
}
⚠️ 踩坑提示:确保apply()
调用在安全链配置的末尾,避免被其他配置覆盖。
高级用法
默认启用配置器:在META-INF/spring.factories
中声明:
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = com.baeldung.dsl.ClientErrorLoggingConfigurer
手动禁用配置器:
//...
.apply(clientErrorLogging()).disable();
4. 总结
本文展示了Spring Security的高级特性——**如何创建自定义SecurityConfigurer
**。这种模式特别适合:
- 封装可复用的安全逻辑
- 实现复杂的安全扩展
- 保持配置代码的整洁性
完整示例代码请查看GitHub仓库。