Rumah  >  Artikel  >  Java  >  Cara menggunakan pensirilan Jackson untuk mencapai penyahpekaan data di Jawa

Cara menggunakan pensirilan Jackson untuk mencapai penyahpekaan data di Jawa

王林
王林ke hadapan
2023-04-18 09:46:10752semak imbas

    1. Latar Belakang

    Dalam projek, beberapa maklumat sensitif tidak boleh dipaparkan secara langsung, seperti nombor telefon bimbit pelanggan, kad pengenalan, nombor plat dan maklumat lain. Penyahpekaan data diperlukan untuk mengelakkan kebocoran privasi pelanggan. Penyahpekaan bermaksud merawat sebahagian daripada data dengan simbol penyahpekaan (*).

    2. Matlamat

    • Apabila pelayan memulangkan data, gunakan pensirilan Jackson untuk melengkapkan penyahpekaan data dan mencapai paparan maklumat sensitif yang dinyahpeka.

    • Kurangkan jumlah pembangunan berulang dan tingkatkan kecekapan pembangunan

    • Bentuk peraturan penyahpekaan bersatu dan berkesan

    • Kaedah penyahpekaan boleh berdasarkan mengatasi pelaksanaan penyahpekaan lalai untuk merealisasikan keperluan penyahpekaan bagi senario perniagaan diperibadikan boleh skala dan boleh disesuaikan

    3.1 Pelaksanaan utama

    3.1 Tersuai pelaksanaan bersiri yang tidak sensitif berdasarkan Jackson

    StdSerializer: Kelas asas yang digunakan oleh semua penyeri standard Ini adalah asas yang disyorkan untuk menulis jenis penyeri tersuai.

    ContextualSerializer: ialah satu lagi antara muka berkaitan siri yang disediakan oleh Jackson Fungsinya adalah untuk menyesuaikan JsonSerializer melalui maklumat kontekstual yang diketahui oleh medan.

    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);
            }

    Nota: createContextual boleh mendapatkan jenis medan dan anotasi. Apabila medan mempunyai anotasi tersuai, ambil nilai dalam anotasi dan buat kaedah bersiri tersuai, supaya nilai boleh diperoleh dalam kaedah bersiri. Kaedah createContextual hanya akan dipanggil pada kali pertama medan disiri (kerana maklumat konteks medan tidak akan berubah semasa masa jalan), jadi tidak perlu risau tentang isu prestasi.

    3.2 Takrif antara muka penyahpekaan dan pelaksanaan kilang

    3.2.1 Takrif antara muka penyahpeka

    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 Kilang penyahpeka pelaksanaan

    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 Pelaksanaan desensitizer yang biasa digunakan

    3.3.1 Pelaksanaan penyahpekaan lalai

    tersedia Berdasarkan pelaksanaan lalai, lanjutkan pelaksanaan senario diperibadikan

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

    3.3.2 Penyahpeka nombor telefon mudah alih

    Mencapai penyahpekaan 4 digit tengah nombor telefon mudah alih

    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 Definisi Anotasi

    Gunakan @JacksonAnnotationsInside untuk melaksanakan anotasi tersuai untuk meningkatkan kemudahan penggunaan

    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 Anotasi penyahpekaan lalai

    4. Contoh penggunaan & analisis proses pelaksanaan
    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 {
    }

    Rajah kelas program

    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());
        }

    Cara menggunakan pensirilan Jackson untuk mencapai penyahpekaan data di Jawa**Analisis Proses Pelaksanaan**

    1. Panggil JsonUtil.toJsonString() untuk memulakan siri 2. Kenal pasti atribut pada mudah alih Anotasi @MobileNoDesensitize (3.4.2 di atas)

    3. Panggil ObjectDesensitizeSerializer#createContextual (3.1 & 3.2 di atas), kembalikan JsonSerializer Cara menggunakan pensirilan Jackson untuk mencapai penyahpekaan data di Jawa

    4. Panggil penyahpekaan nombor telefon mudah alih untuk melaksanakan MobileNoDesensitization#desensitize (3.3.2 di atas)

    5. Keluarkan hasil bersiri yang dinyahpeka, {"mobile":"133****5678"}

    Tidak sukar untuk mencari proses pelaksanaan teras Ini adalah langkah 3, tetapi bagaimanakah @ MobileNoDesensitize dan ObjectDesensitizeSerializer disambungkan?

    Cuba selesaikan pautan rujukan: @MobileNoDesensitize -> @Desensitize -> @JsonSerialize -> dalam Dalam pelaksanaan ObjectDesensitizeSerializer, kami nampaknya tidak menemui hubungan panggilan langsung pautan di atas

    Ini perlu bercakap tentang konsep meta-anotasi Jackson

    • Melalui mekanisme "anotasi kombo" (anotasi gabungan, anotasi berpakatan) adalah mungkin untuk mengarahkan Jackson menggunakan anotasi metanya sendiri dan bukannya menggunakan anotasi sasaran, dengan itu mencapai reka bentuk pelaksanaan penyahpekaan tersuai Sasaran.

    Atas ialah kandungan terperinci Cara menggunakan pensirilan Jackson untuk mencapai penyahpekaan data di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam