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 (*).
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
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.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.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;
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 pelaksanaanpackage 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 { /** * '*'脱敏符 */ 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()); }
**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
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 JacksonMelalui 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!