如何阻止org.springframework.security.web.firewall.RequestRejectedException的堆栈跟踪日志
Spring Boot 抑制含无效字符URL请求的堆栈日志方案
当客户端请求包含;这类无效字符的URL时,Spring Security的StrictHttpFirewall会抛出RequestRejectedException,默认配置下会输出完整堆栈信息污染日志,可通过以下几种方式解决:
方法一:自定义异常处理器拦截日志
通过自定义RequestRejectedHandler捕获该异常,只输出简洁的错误信息,避免打印堆栈。
1. 实现自定义处理器
import org.springframework.security.web.firewall.RequestRejectedHandler; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CustomRequestRejectedHandler implements RequestRejectedHandler { private static final Logger logger = LoggerFactory.getLogger(CustomRequestRejectedHandler.class); @Override public void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException ex) { // 仅输出关键信息,不打印堆栈 logger.warn("请求被拒绝: {},原因: {}", request.getRequestURI(), ex.getMessage()); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); } }
2. 注册到Security配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.security.web.firewall.RequestRejectedHandler; @Configuration public class SecurityConfig { @Bean public RequestRejectedHandler requestRejectedHandler() { return new CustomRequestRejectedHandler(); } @Bean public HttpFirewall strictHttpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setRequestRejectedHandler(requestRejectedHandler()); return firewall; } }
方法二:通过日志配置过滤堆栈
无需修改代码,直接调整日志配置文件,让RequestRejectedException不输出堆栈信息。
Logback配置(logback-spring.xml)
添加过滤器针对该异常屏蔽堆栈:
<configuration> <!-- 其他原有配置 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 屏蔽RequestRejectedException的堆栈输出 --> <logger name="org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]" level="ERROR"> <filter class="ch.qos.logback.classic.filter.ThrowableProxyConverter"> <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator"> <expression>throwable instanceof org.springframework.security.web.firewall.RequestRejectedException</expression> </evaluator> <onMatch>DENY</onMatch> </filter> <appender-ref ref="CONSOLE"/> </logger> </configuration>
application.properties配置
通过简单配置降低日志输出级别:
# 限制Spring Security防火墙日志级别为WARN,减少冗余输出 logging.level.org.springframework.security.web.firewall=WARN # 让dispatcherServlet仅输出错误信息,不打印堆栈 logging.level.org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]=ERROR logging.exception-conversion-word=
方法三:放宽防火墙URL规则(谨慎使用)
如果业务场景确实需要允许URL中包含;这类字符,可以修改StrictHttpFirewall的限制规则:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; @Configuration public class SecurityConfig { @Bean public HttpFirewall allowSemicolonHttpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); // 允许URL中包含分号 firewall.setAllowSemicolon(true); // 如需允许其他特殊字符,可开启对应配置 // firewall.setAllowUrlEncodedSlash(true); return firewall; } }
注意:此方法会降低安全防护等级,仅在确认业务场景安全的前提下使用。
内容的提问来源于stack exchange,提问作者geschema
相关产品推荐
相关产品推荐

