如何修改Spring Integration DirectChannel默认日志以排除Authorization头?
当然有办法搞定这个问题!既可以避免日志被超长令牌撑得难以阅读,又能符合生产环境的安全要求,下面给你几个实用的方案:
方案1:自定义DirectChannel,在日志输出时脱敏Authorization头
这个方法直接针对DirectChannel的preSend日志,只修改日志显示,完全不影响实际业务中的消息头:
- 创建自定义DirectChannel子类,重写
send方法,在输出调试日志时替换Authorization头为脱敏内容:
import org.springframework.integration.channel.DirectChannel; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageHeaderAccessor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class RedactingDirectChannel extends DirectChannel { private static final Log logger = LogFactory.getLog(RedactingDirectChannel.class); @Override public boolean send(Message<?> message, long timeout) { if (logger.isDebugEnabled()) { // 创建消息头的可变副本,替换Authorization头 MessageHeaderAccessor headerAccessor = MessageHeaderAccessor.getMutableAccessor(message); headerAccessor.setHeader("authorization", "***REDACTED***"); // 构造脱敏后的消息用于日志输出 Message<?> redactedMessage = new GenericMessage<>(message.getPayload(), headerAccessor.getMessageHeaders()); logger.debug("preSend on channel '{}', message: {}", this.getName(), redactedMessage); } // 调用父类方法发送原始消息,不影响业务逻辑 return super.send(message, timeout); } }
- 在Spring配置中用这个自定义通道替换默认的DirectChannel:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.MessageChannel; @Configuration public class IntegrationConfig { @Bean public MessageChannel myChannel() { return new RedactingDirectChannel(); } }
方案2:通过日志框架(如Logback)全局脱敏Authorization头
如果不想修改业务代码,也可以通过日志框架的自定义转换器全局拦截并替换日志中的敏感内容,适用于所有组件的日志输出:
- 创建Logback自定义转换器类:
import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import java.util.regex.Pattern; public class AuthHeaderRedactorConverter extends ClassicConverter { // 匹配Authorization头的正则表达式 private static final Pattern AUTH_HEADER_PATTERN = Pattern.compile("authorization=Bearer\\s+\\S+"); @Override public String convert(ILoggingEvent event) { String originalMessage = event.getFormattedMessage(); if (originalMessage != null) { // 替换匹配到的Authorization内容为脱敏字符串 return AUTH_HEADER_PATTERN.matcher(originalMessage).replaceAll("authorization=***REDACTED***"); } return originalMessage; } }
- 在
logback.xml中配置这个转换器并应用到日志格式:
<configuration> <!-- 注册自定义转换器 --> <conversionRule conversionWord="redactAuth" converterClass="com.yourpackage.AuthHeaderRedactorConverter" /> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 使用自定义转换器处理日志消息 --> <pattern>%d{ISO8601} | %thread | %logger | send line: %L | %redactAuth{%msg}%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="CONSOLE" /> </root> </configuration>
方案3:使用Spring Integration的MessageLoggingStrategy(针对LoggingHandler)
如果你的日志是通过Spring Integration的LoggingHandler(比如<logging-channel-adapter>)输出的,可以通过自定义MessageLoggingStrategy排除指定头:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.logging.DefaultMessageLoggingStrategy; import org.springframework.integration.logging.MessageLoggingStrategy; @Configuration public class LoggingConfig { @Bean public MessageLoggingStrategy customMessageLoggingStrategy() { DefaultMessageLoggingStrategy strategy = new DefaultMessageLoggingStrategy(); // 排除Authorization头不输出到日志 strategy.setExcludedHeaders("authorization"); return strategy; } }
注意:这个方案只对LoggingHandler的日志生效,如果你需要处理DirectChannel自身的preSend日志,还是推荐前两个方案。
内容的提问来源于stack exchange,提问作者StevenPG
相关产品推荐
相关产品推荐

