1. 避免直接记录敏感信息
- 思路:在代码层面,避免将敏感信息作为参数传递给日志记录方法。例如,如果有一个登录方法,不要将用户输入的密码直接传递给日志方法。
- 示例(以SLF4J为例):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoginService {
private static final Logger logger = LoggerFactory.getLogger(LoginService.class);
public void login(String username, String password) {
// 错误做法:记录密码
// logger.info("User {} logged in with password {}", username, password);
// 正确做法:不记录密码
logger.info("User {} logged in", username);
}
}
2. 过滤敏感信息
- 思路:如果在日志配置文件(如Log4j的
log4j.properties
或log4j.xml
,SLF4J结合Logback的logback.xml
)中,可以配置过滤器来过滤掉敏感信息。例如,可以使用正则表达式匹配并替换敏感信息。
- 示例(以Logback为例,在
logback.xml
中配置):
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
<expression>return message.matches(".*password=\\S+.*");</expression>
</evaluator>
<OnMismatch>NEUTRAL</OnMismatch>
<OnMatch>DENY</OnMatch>
</filter>
</encoder>
</appender>
3. 使用占位符和参数化日志
- 思路:在日志消息模板中使用占位符,然后通过参数传递非敏感信息。这样即使日志配置错误或意外泄露,敏感信息也不会暴露在日志文本中。
- 示例(以Log4j为例):
import org.apache.log4j.Logger;
public class UserService {
private static final Logger logger = Logger.getLogger(UserService.class);
public void updateUser(String userId, String newEmail) {
logger.info("User with ID {} updated email to {}", userId, newEmail);
}
}
4. 对敏感信息进行加密处理
- 思路:在记录日志之前,对敏感信息进行加密。这样即使日志被泄露,获取到的也是加密后的内容,难以直接获取敏感信息。
- 示例(使用Java自带的
MessageDigest
进行简单哈希加密,实际应用中需更安全的加密算法):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class UserRegistrationService {
private static final Logger logger = LoggerFactory.getLogger(UserRegistrationService.class);
public void registerUser(String username, String password) {
String encryptedPassword = encryptPassword(password);
logger.info("User {} registered with encrypted password {}", username, encryptedPassword);
}
private String encryptPassword(String password) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(password.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}