>  기사  >  Java  >  Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법

Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법

王林
王林앞으로
2023-04-18 09:46:10752검색

    1. 배경

    프로젝트에서는 고객 휴대폰 번호, 신분증, 차량 번호판 번호 및 기타 정보와 같은 일부 민감한 정보를 직접 표시할 수 없습니다. 고객 개인 정보 보호. 감도 줄이기란 데이터의 일부를 감도 줄이기 기호(*)로 처리하는 것을 의미합니다.

    2. 목표

    • 서버가 데이터를 반환하면 Jackson 직렬화를 사용하여 데이터 둔감화를 완료하고 민감한 정보를 둔감하게 표시합니다.

    • 반복되는 개발 양을 줄이고 개발 효율성 향상

    • 통합되고 효과적인 둔감화 규칙 형성

    • 확장 가능하고 사용자 정의 가능한 개인화 서비스를 달성하기 위해 기본 둔감화 구현을 재정의하는 둔감화 방법을 기반으로 할 수 있음 of the scene

    3. 주요 구현

    3.1 Jackson을 기반으로 한 사용자 정의 둔감화 직렬화 구현

    StdSerializer: 모든 표준 직렬화기에서 사용하는 기본 클래스. 사용자 정의 직렬화 작성을 위한 기본 클래스입니다. 프로그램에서 사용하도록 권장됩니다. .

    ContextualSerializer: 는 Jackson이 제공하는 또 다른 직렬화 관련 인터페이스입니다. 해당 기능은 필드에서 알려진 상황별 정보를 통해 JsonSerializer를 사용자 정의하는 것입니다.

    package com.jd.ccmp.ctm.constraints.serializer;
    
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.BeanProperty;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.ser.ContextualSerializer;
    import com.fasterxml.jackson.databind.ser.std.StdSerializer;
    import com.jd.ccmp.ctm.constraints.Symbol;
    import com.jd.ccmp.ctm.constraints.annotation.Desensitize;
    import com.jd.ccmp.ctm.constraints.desensitization.Desensitization;
    import com.jd.ccmp.ctm.constraints.desensitization.DesensitizationFactory;
    import com.jd.ccmp.ctm.constraints.desensitization.DefaultDesensitization;
    
    
    
    
    import java.io.IOException;
    
    
    
    
    /**
     * 脱敏序列化器
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:10
     */
    public class ObjectDesensitizeSerializer extends StdSerializer<Object> implements ContextualSerializer {
        private static final long serialVersionUID = -7868746622368564541L;
        private transient Desensitization<Object> desensitization;
        protected ObjectDesensitizeSerializer() {
            super(Object.class);
        }
        public Desensitization<Object> getDesensitization() {
            return desensitization;
        }
        public void setDesensitization(Desensitization<Object> desensitization) {
            this.desensitization = desensitization;
        }
        @Override
        public JsonSerializer<Object> createContextual(SerializerProvider prov, BeanProperty property) {
    //获取属性注解
            Desensitize annotation = property.getAnnotation(Desensitize.class);
            return createContextual(annotation.desensitization());
        }
        @SuppressWarnings("unchecked")
        public JsonSerializer<Object> createContextual(Class<? extends Desensitization<?>> clazz) {
            ObjectDesensitizeSerializer serializer = new ObjectDesensitizeSerializer();
            if (clazz != DefaultDesensitization.class) {
                serializer.setDesensitization((Desensitization<Object>) DesensitizationFactory.getDesensitization(clazz));
            }
            return serializer;
        }
        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            Desensitization<Object> objectDesensitization = getDesensitization();
            if (objectDesensitization != null) {
                try {
                    gen.writeObject(objectDesensitization.desensitize(value));
                } catch (Exception e) {
                    gen.writeObject(value);
                }
            } else if (value instanceof String) {
                gen.writeString(Symbol.getSymbol(((String) value).length(), Symbol.STAR));
            } else {
                gen.writeObject(value);
            }

    참고: createContextual은 필드 유형과 주석을 가져올 수 있습니다. 필드에 사용자 정의 주석이 있는 경우 주석의 값을 가져와 사용자 정의 직렬화 메서드를 생성하면 해당 값을 직렬화 메서드에서 얻을 수 있습니다. createContextual 메서드는 필드가 처음 직렬화될 때만 호출되므로(필드의 컨텍스트 정보는 런타임 중에 변경되지 않으므로) 성능 문제에 대해 걱정할 필요가 없습니다.

    3.2 Desensitizer 인터페이스 정의 및 공장 구현

    3.2.1 Desensitizer 인터페이스 정의

    package com.jd.ccmp.ctm.constraints.desensitization;
    
    
    /**
     * 脱敏器
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 10:56
     */
    public interface Desensitization<T> {
        /**
         * 脱敏实现
         *
         * @param target 脱敏对象
         * @return 脱敏返回结果
         */
        T desensitize(T target);
    }

    3.2.2 Desensitizer 공장 구현

    package com.jd.ccmp.ctm.constraints.desensitization;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * 工厂方法
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 10:58
     */
    public class DesensitizationFactory {
        private DesensitizationFactory() {
        }
        private static final Map<Class<?>, Desensitization<?>> map = new HashMap<>();
    
    
    
    
        @SuppressWarnings("all")
        public static Desensitization<?> getDesensitization(Class<?> clazz) {
            if (clazz.isInterface()) {
                throw new UnsupportedOperationException("desensitization is interface, what is expected is an implementation class !");
            }
            return map.computeIfAbsent(clazz, key -> {
                try {
                    return (Desensitization<?>) clazz.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    throw new UnsupportedOperationException(e.getMessage(), e);
                }
            });

    3.3 일반적으로 사용되는 Desensitizer 구현

    3.3 .1 기본 desensit 구현 구현

    기본 구현을 기반으로 확장하여 개인화된 시나리오 구현 가능

    package com.jd.ccmp.ctm.constraints.desensitization;
    
    
    /**
     * 默认脱敏实现
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:01
     */
    public interface DefaultDesensitization extends Desensitization<String> {
    }

    3.3.2 휴대폰 번호 감도 줄이기

    휴대폰 번호 중간 4자리 감도 줄이기 구현

    package com.jd.ccmp.ctm.constraints.desensitization;
    import com.jd.ccmp.ctm.constraints.Symbol;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    
    /**
     * 手机号脱敏器,保留前3位和后4位
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:02
     */
    public class MobileNoDesensitization implements DefaultDesensitization {
        /**
         * 手机号正则
         */
        private static final Pattern DEFAULT_PATTERN = Pattern.compile("(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}");
    
    
    
    
        @Override
        public String desensitize(String target) {
            Matcher matcher = DEFAULT_PATTERN.matcher(target);
            while (matcher.find()) {
                String group = matcher.group();
                target = target.replace(group, group.substring(0, 3) + Symbol.getSymbol(4, Symbol.STAR) + group.substring(7, 11));
            }
            return target;

    3.4 주석 정의

    사용자 정의 주석 구현 @JacksonAnnotationsInside를 통해 사용 편의성 향상

    package com.jd.ccmp.ctm.constraints.annotation;
    import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    import com.jd.ccmp.ctm.constraints.desensitization.Desensitization;
    import com.jd.ccmp.ctm.constraints.serializer.ObjectDesensitizeSerializer;
    import java.lang.annotation.*;
    
    
    /**
     * 脱敏注解
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:09
     */
    @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotationsInside
    @JsonSerialize(using = ObjectDesensitizeSerializer.class)
    @Documented
    public @interface Desensitize {
        /**
         * 对象脱敏器实现
         */
        @SuppressWarnings("all")
        Class<? extends Desensitization<?>> desensitization();

    3.4.1 기본 둔감화 주석

    package com.jd.ccmp.ctm.constraints.annotation;
    import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
    import com.jd.ccmp.ctm.constraints.desensitization.DefaultDesensitization;
    import java.lang.annotation.*;
    
    
    
    
    /**
     * 默认脱敏注解
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:14
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotationsInside
    @Desensitize(desensitization = DefaultDesensitization.class)
    @Documented
    public @interface DefaultDesensitize {

    3.4.2 휴대전화 번호 둔감화 주석

    package com.jd.ccmp.ctm.constraints.annotation;
    import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
    import com.jd.ccmp.ctm.constraints.desensitization.MobileNoDesensitization;
    import java.lang.annotation.*;
    
    
    /**
     * 手机号脱敏
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 11:18
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotationsInside
    @Desensitize(desensitization = MobileNoDesensitization.class)
    @Documented
    public @interface MobileNoDesensitize {
    }

    3.5 둔감화 기호 정의

    지원됨 * 또는 등의 둔감화 기호 지정 ^_^

    package com.jd.ccmp.ctm.constraints;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    
    
    /**
     * 脱敏符号
     *
     * @author zhangxiaoxu15
     * @date 2022/2/8 10:53
     */
    public class Symbol {
        /**
         * &#39;*&#39;脱敏符
         */
        public static final String STAR = "*";
        private Symbol() {}
        /**
         * 获取符号
         *
         * @param number 符号个数
         * @param symbol 符号
         */
        public static String getSymbol(int number, String symbol) {
            return IntStream.range(0, number).mapToObj(i -> symbol).collect(Collectors.joining());
        }

    4. 사용 예 및 실행 프로세스 분석

    Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법

    프로그램 클래스 다이어그램

    Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법

    **실행 프로세스 분석**

    1. JsonUtil.toJsonString()을 호출하여 직렬화를 시작합니다

    2. mobile 속성에서 @MobileNoDesensitize 주석을 식별합니다(위의 3.4.2)

    3. ObjectDesensitizeSerializer#createContextual(위의 3.1 및 3.2)을 호출하고 JsonSerializer

    를 반환합니다. 4. 휴대폰 번호 감도 줄이기를 호출하여 MobileNoDesensitization#desensitize를 구현합니다. (위 3.3.2)

    5. 둔감화된 직렬화 결과 {"mobile":"133****5678"}을 출력합니다.

    핵심을 찾는 것은 어렵지 않습니다. 실행 과정은 3단계인데 어떻게 됩니까? @MobileNoDesensitize와 ObjectDesensitizeSerializer가 연결되었나요?

    • 참조 링크를 정렬해 보세요: @MobileNoDesensitize -> @Desensitize -> ObjectDesensitizeSerializer

    • 그러나 ObjectDesensitizeSerializer 구현에서는 위의 링크 관계

    • 이것은 Jackson 메타 주석의 개념에 대해 언급해야 합니다

    //**Jackson元注解**
    //1.提到元注解这个词,大家会想到@Target、@Retention、@Documented、@Inherited
    //2.Jackson也以同样的思路设计了@JacksonAnnotationsInside
    
    
    /**
     * Meta-annotation (annotations used on other annotations)
     * used for indicating that instead of using target annotation
     * (annotation annotated with this annotation),
     * Jackson should use meta-annotations it has.
     * This can be useful in creating "combo-annotations" by having
     * a container annotation, which needs to be annotated with this
     * annotation as well as all annotations it &#39;contains&#39;.
     * 
     * @since 2.0
     */
    @Target({ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotation
    public @interface JacksonAnnotationsInside
    {
    }

    Jackson에게 메타 주석을 사용하도록 지시하는 것은 "콤보 주석"(결합 주석, 번들 주석) 메커니즘을 통해서입니다. - 대상 주석을 사용하는 대신 자신이 소유한 주석을 사용하여 사용자 정의 둔감화를 활성화하여 설계 목표를 달성합니다.

    위 내용은 Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제