001package run.iget.framework.desensitization.serializer;
002
003import java.io.IOException;
004import java.util.Objects;
005import java.util.function.Function;
006
007import com.fasterxml.jackson.core.JsonGenerator;
008import com.fasterxml.jackson.databind.BeanProperty;
009import com.fasterxml.jackson.databind.JsonMappingException;
010import com.fasterxml.jackson.databind.JsonSerializer;
011import com.fasterxml.jackson.databind.SerializerProvider;
012import com.fasterxml.jackson.databind.ser.ContextualSerializer;
013
014import lombok.extern.slf4j.Slf4j;
015import run.iget.framework.desensitization.annotation.Desensitization;
016import run.iget.framework.desensitization.context.DesensitizationThreadLocalContext;
017
018/**
019 * 代码千万行,注释第一行,注释不规范,迭代两行泪
020 * ---------------类描述-----------------
021 * jackson序列化输出字段脱敏
022 * ---------------类描述-----------------
023 * @author 大周
024 * @since 2022/8/22 11:58
025 */
026@Slf4j
027public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
028
029    private Function<String, String> desensitizationHandler;
030
031    public DesensitizeSerializer() {
032    }
033
034    public DesensitizeSerializer(Function desensitizationHandler) {
035        this.desensitizationHandler = desensitizationHandler;
036    }
037
038    @Override
039    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)
040            throws JsonMappingException {
041        log.info("---------------------------------createContextual");
042        if (Objects.isNull(beanProperty)) {
043            return serializerProvider.findNullValueSerializer(beanProperty);
044        }
045        // 非 String 类直接跳过
046        if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
047            Function function = getDesensitization(beanProperty);
048            if (function != null) {
049                return new DesensitizeSerializer(function);
050            }
051        }
052        return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
053    }
054
055    @Override
056    public void serialize(String source, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
057            throws IOException {
058        if (DesensitizationThreadLocalContext.isNeedDesensitization() && Objects.nonNull(desensitizationHandler)) {
059            jsonGenerator.writeString(desensitizationHandler.apply(source));
060        } else {
061            jsonGenerator.writeString(source);
062        }
063    }
064
065    private Function getDesensitization(BeanProperty beanProperty) {
066        Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
067        if (desensitization == null) {
068            desensitization = beanProperty.getContextAnnotation(Desensitization.class);
069        }
070        if (desensitization == null) {
071            return null;
072        }
073        Function function = desensitization.type().getFunction();
074        Class<? extends Function> handlerClass = desensitization.handler();
075        if (handlerClass != null) {
076            try {
077                function = handlerClass.newInstance();
078            } catch (Exception e) {
079                log.error("can not newInstance", e);
080            }
081        }
082        return function;
083    }
084}