用spring标签实现字段的脱敏

问题描述

在springboot中实现数据库脱敏,可以选择在对象序列化之前进行处理脱敏,接下来就是具体的操作了。(参考了网上的资料进行了整理)

解决方案

第一步

构建枚举类,用来识别每个脱敏字段

/**
 * @author tori
 * 2018/7/16 上午11:19
 */
public enum SensitiveType {
    /** 手机号 */
    MOBILE,

    /** 电子邮箱 */
    EMAIL,

    /** openId */
    OPEN_ID
}

第二步

创建处理脱敏字段的工具类(这里只展示了mobile,其他类推)

/**
 * @author tori
 * 2018/7/16 下午1:57
 */
public class SensitiveUtil {

    public static String mobile(String mobile) {
        if (StringUtils.isBlank(mobile)) {
            return "";
        }

        return StringUtils.left(mobile, 2).concat(
                StringUtils.removeStart(
                        StringUtils.leftPad(
                            StringUtils.right(mobile, 4), StringUtils.length(mobile), "*"),
                        "***"));
    }
}

第三步

创建标签类(构建标签)

/**
 * @author tori
 * 2018/7/16 上午11:33
 */

//@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveInfoSerialize.class)
public @interface SensitiveInfo {

    SensitiveType value();
}

有时在写标签类时会碰到@Target,@Retention还有@Order的用法,这里简单的概括一下:

@Target

这个注解就是表明该注解类能够作用的范围,也就是能够注解在哪,比如 类、方法、参数等。 
下面是他的一些参数: 
@Target(ElementType.TYPE) //接口、类、枚举、注解 
@Target(ElementType.FIELD) //字段、枚举的常量 
@Target(ElementType.METHOD) //方法 
@Target(ElementType.PARAMETER) //方法参数 
@Target(ElementType.CONSTRUCTOR) //构造函数 
@Target(ElementType.LOCAL_VARIABLE)//局部变量 
@Target(ElementType.ANNOTATION_TYPE)//注解 
@Target(ElementType.PACKAGE) ///包 
里面的参数是可以多选的,使用方法比如@Target({ElementType.METHOD,ElementType.TYPE})。

@Retention

这个注解是保留说明,也就是表明这个注解所注解的类能在哪里保留,他有三个属性值: 
RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略 
RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略 
RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。 
从上面可以看出一般使用的事第三个属性,其余两个属性,说实话 我也不清楚什么情况下使用这两种。

@Order

@Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。如:1,2 等等。值越小拥有越高的优先级。Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647

第四步

最重要的标签序列化处理类:

/**
 * @author tori
 * 2018/7/16 下午1:33
 */
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveType type;

    public SensitiveInfoSerialize(SensitiveType type) {
        this.type = type;
    }

    public SensitiveInfoSerialize() {}

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        switch (this.type) {
            case MOBILE:
                gen.writeString(SensitiveUtil.mobile(value));
                break;
            case EMAIL:
                gen.writeString(SensitiveUtil.email(value));
                break;
            case OPEN_ID:
                gen.writeString(SensitiveUtil.openId(value));
                break;
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if (property != null) { // 为空直接跳过
            if (Objects.equals(property.getType().getRawClass(), String.class)) { // 非 String 类直接跳过
                SensitiveInfo sensitiveInfo = property.getAnnotation(SensitiveInfo.class);
                if (sensitiveInfo == null) {
                    sensitiveInfo = property.getContextAnnotation(SensitiveInfo.class);
                }
                if (sensitiveInfo != null) { // 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerialize

                    return new SensitiveInfoSerialize(sensitiveInfo.value());
                }
            }
            return prov.findValueSerializer(property.getType(), property);
        }
        return prov.findNullValueSerializer(property);
    }
}

最后一步

就是使用和测试啦:

 /**
  * 手机号码
  */
@SensitiveInfo(SensitiveType.MOBILE)
private String mobile;

这样一来获得的json中mobile,email,openId就可以隐藏部分内容,实现脱敏了。

以上是对spring标签实现脱敏的流程描述。☺

猜你喜欢

转载自blog.csdn.net/qq_33235059/article/details/81069095