프로젝트에서는 고객 휴대폰 번호, 신분증, 차량 번호판 번호 및 기타 정보와 같은 일부 민감한 정보를 직접 표시할 수 없습니다. 고객 개인 정보 보호. 감도 줄이기란 데이터의 일부를 감도 줄이기 기호(*)로 처리하는 것을 의미합니다.
서버가 데이터를 반환하면 Jackson 직렬화를 사용하여 데이터 둔감화를 완료하고 민감한 정보를 둔감하게 표시합니다.
반복되는 개발 양을 줄이고 개발 효율성 향상
통합되고 효과적인 둔감화 규칙 형성
확장 가능하고 사용자 정의 가능한 개인화 서비스를 달성하기 위해 기본 둔감화 구현을 재정의하는 둔감화 방법을 기반으로 할 수 있음 of the scene
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.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 .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;
사용자 정의 주석 구현 @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 { }
지원됨 * 또는 등의 둔감화 기호 지정 ^_^
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()); }
프로그램 클래스 다이어그램
**실행 프로세스 분석**
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 'contains'. * * @since 2.0 */ @Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation public @interface JacksonAnnotationsInside { }
Jackson에게 메타 주석을 사용하도록 지시하는 것은 "콤보 주석"(결합 주석, 번들 주석) 메커니즘을 통해서입니다. - 대상 주석을 사용하는 대신 자신이 소유한 주석을 사용하여 사용자 정의 둔감화를 활성화하여 설계 목표를 달성합니다.
위 내용은 Java에서 데이터 둔감화를 달성하기 위해 Jackson 직렬화를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!