解决Spring Security因含//的恶意URL抛出RequestRejectedException问题
解决Spring Security防火墙拦截恶意URL时的日志报错问题
你的核心问题是Spring Security的StrictHttpFirewall拦截含//的恶意URL后,会抛出RequestRejectedException并打印完整错误堆栈,但你希望保持拦截规则的同时,避免日志中出现错误级别的堆栈信息。由于Spring Security过滤器链优先级高于自定义过滤器,直接用自定义过滤器无法提前拦截,以下是两种可靠解决方案:
方案一:自定义RequestRejectedHandler(推荐)
通过实现Spring Security的RequestRejectedHandler接口,自定义异常处理逻辑,控制返回状态码和日志输出级别,既保留拦截能力,又避免错误堆栈刷屏。
代码实现
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.firewall.RequestRejectedException; import org.springframework.security.web.firewall.RequestRejectedHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 这里添加你的其他安全配置(如授权、认证规则) .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()) // 配置自定义的请求拒绝处理器 .exceptionHandling(exceptionConfig -> exceptionConfig.requestRejectedHandler(customRequestRejectedHandler()) ); return http.build(); } @Bean public RequestRejectedHandler customRequestRejectedHandler() { return new RequestRejectedHandler() { private final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException ex) throws IOException, ServletException { // 返回404状态码,和你当前浏览器收到的一致 response.sendError(HttpServletResponse.SC_NOT_FOUND); // 仅记录警告级别的日志,不打印完整堆栈 logger.warn("拦截恶意请求: URL包含潜在危险字符 - 请求地址: {}", request.getRequestURI()); } }; } }
方案二:调整日志级别(快速临时方案)
如果你不想编写自定义代码,可以直接调整Spring Security防火墙模块的日志级别,将其从ERROR改为WARN,这样就不会打印错误堆栈。
配置方式(Spring Boot)
在application.properties中添加:
logging.level.org.springframework.security.web.firewall=WARN
或者在application.yml中:
logging: level: org.springframework.security.web.firewall: WARN
注意:这种方式会将该包下所有日志降级为WARN级别,可能会忽略其他潜在的严重错误,因此仅推荐作为临时方案。
为什么自定义过滤器无效?
Spring Security的FilterChainProxy默认在所有自定义Servlet过滤器之前注册,请求会先经过Spring Security的防火墙校验,校验失败抛出异常后,请求根本不会到达你的自定义过滤器,因此必须通过Spring Security自身的异常处理机制来处理该异常。
内容的提问来源于stack exchange,提问作者inquisitive
相关产品推荐
相关产品推荐

