Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How masking of sensitive data is achieved using slf4j framework?

Tags:

slf4j

I wanted to mask the sensitive data like username/password using an slf4j framework. Immediate help is appreciated. Thanks in advance.

like image 936
Raghvendra Avatar asked Sep 06 '25 00:09

Raghvendra


1 Answers

Try this one.

  1. First of all, we should create a class for handling our logs (each row)

    public class PatternMaskingLayout extends PatternLayout {
    
        private Pattern multilinePattern;
        private List<String> maskPatterns = new ArrayList<>();
    
        public void addMaskPattern(String maskPattern) { // invoked for every single entry in the xml
            maskPatterns.add(maskPattern);
            multilinePattern = Pattern.compile(
                String.join("|", maskPatterns), // build pattern using logical OR
                Pattern.MULTILINE);
        }
    
        @Override
        public String doLayout(ILoggingEvent event) {
            return maskMessage(super.doLayout(event)); // calling superclass method is required
        }
    
        private String maskMessage(String message) {
            if (multilinePattern == null) {
                return message;
            }
            StringBuilder sb = new StringBuilder(message);
            Matcher matcher = multilinePattern.matcher(sb);
            while (matcher.find()) {
                if (matcher.group().contains("creditCard")) {
                    maskCreditCard(sb, matcher);
                } else if (matcher.group().contains("email")) {
                    // your logic for this case
                }
            }
            return sb.toString();
        }
    
        private void maskCreditCard(StringBuilder sb, Matcher matcher) {
            //here is our main logic for masking sensitive data
            String targetExpression = matcher.group();
            String[] split = targetExpression.split("=");
            String pan = split[1];
            String maskedPan = Utils.getMaskedPan(pan);
            int start = matcher.start() + split[0].length() + 1;
            int end = matcher.end();
            sb.replace(start, end, maskedPan);
        }
    }
    
  2. The second step is we should create appender for logback into logback.xml

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="com.bpcbt.micro.utils.PatternMaskingLayout">
                <maskPattern>creditCard=\d+</maskPattern> <!-- SourcePan pattern -->
                <pattern>%d{dd/MM/yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex</pattern>-->
            </layout>
        </encoder>
    </appender>
    
  3. Now we can use logger into our code

    log.info("card context set for creditCard={}", creditCard);
    
  4. List item

As a result, we will see

one row from logs

card context set for creditCard=11111******111

without these options, our logs would be like this row

card context set for creditCard=1111111111111
like image 115
Alexandr Kovalenko Avatar answered Sep 07 '25 22:09

Alexandr Kovalenko