栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot基于注解方式处理接口数据脱敏

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot基于注解方式处理接口数据脱敏

1.定义注解

创建Spring Boot项目添加以下依赖

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            cn.hutool
            hutool-core
            5.7.22
        
    

然后定义Sensitive 注解,@JacksonAnnotationsInside的作用是将@JacksonAnnotation标注的注解作为一个组合注解,这里使用@JacksonAnnotationsInside在@Sensitive 注解中组合@JsonSerialize注解,这样就可以使用JsonSerialize的功能,并且可以拓展自定义属性和隐式得指定自定义序列化器SensitiveSerializer了。

@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {
    
    Type value();

    
    int startInclude() default 0;

    
    int endExclude() default 0;


    
    int overlayRepeat() default 4;


    
    public enum Type {
        
        MOBILE,
        
        CHINESE_NAME,
        
        ID_CARD,
        
        FIXED_PHONE,
        
        ADDRESS,
        
        EMAIL,
        
        BANK_CARD,
        
        CUSTOM_HIDE,
        
        CUSTOM_RETAIN_HIDE,
        
        CUSTOM_OVERLAY,
    }

}
2. 脱敏工具类

创建脱敏工具类SensitiveUtil ,统一封装数据脱敏的方法。

public class SensitiveUtil {


    
    public static String handlerMobile(String mobile) {
        if(StringUtil.isEmpty(mobile)){
            return null;
        }
         return hide(mobile,3,mobile.length() - 4);
    }

    
    public static String handlerPhone(String phone) {
        if(StringUtil.isEmpty(phone)){
            return null;
        }
        return overlay(phone,StringPool.ASTERISK,1,0,phone.length() - 4);
    }


    
    public static String handlerIdCard(String idNum) {
        if(StringUtil.isEmpty(idNum)){
            return null;
        }
        return hide(idNum,6,idNum.length() - 4);
    }

    
    public static String handlerBankCard(String cardNum) {
        if(StringUtil.isEmpty(cardNum)){
            return null;
        }
        return hide(cardNum,6,cardNum.length() - 4);
    }

    
    public static String handlerAddress(String address) {
        if(StringUtil.isEmpty(address)){
            return null;
        }
        return overlay(address,StringPool.ASTERISK,4,9,address.length());
    }


    
    public static String handlerUsername(String username) {
        if(StringUtil.isEmpty(username)){
            return null;
        }
        return hide(username,1,username.length());
    }

    
    public static String handlerFixedPhone(final String num) {
        if(StringUtil.isEmpty(num)){
            return null;
        }
        return overlay(num, StringPool.ASTERISK,4, 0,num.length()-4);
    }

    
    public static String handlerEmail(final String email) {
        if(StringUtil.isEmpty(email)){
            return null;
        }
        final int index = StringUtil.indexOf(email, StringPool.AT_CHAR);
        if (index <= 1) {
            return email;
        } else {
            return hide(email, 1, index);
        }
    }

    
    public static String overlay(String str, String overlay,int overlayRepeat, int start, int end) {
        if (StringUtil.isEmpty(str)) {
            return StringUtil.str(str);
        }
        if (StringUtil.isEmpty(overlay)) {
            overlay = StringPool.EMPTY;
        }
        final int len = str.length();
        if (start < 0) {
            start = 0;
        }
        if (start > len) {
            start = len;
        }
        if (end < 0) {
            end = 0;
        }
        if (end > len) {
            end = len;
        }
        if (start > end) {
            final int temp = start;
            start = end;
            end = temp;
        }
        return str.substring(0, start) + StringUtil.repeat(overlay, overlayRepeat) + str.substring(end);
    }

    
    public static String hide(String str, int startInclude, int endExclude) {
        return hide(str, startInclude, endExclude,StringPool.ASTERISK_CHAR);

    }

    
    public static String hide(String str, int startInclude, int endExclude, char replacedChar) {
        if (StringUtil.isEmpty(str)) {
            return StringUtil.str(str);
        }
        final int strLength = str.length();
        if (startInclude > strLength) {
            return StringUtil.str(str);
        }
        if (endExclude > strLength) {
            endExclude = strLength;
        }
        if (startInclude > endExclude) {
            // 如果起始位置大于结束位置,不替换
            return StringUtil.str(str);
        }

        final char[] chars = new char[strLength];
        for (int i = 0; i < strLength; i++) {
            if (i >= startInclude && i < endExclude) {
                chars[i] = replacedChar;
            } else {
                chars[i] = str.charAt(i);
            }
        }
        return new String(chars);
    }

}
3. 自定义Jackson序列化器

参考Jackson自带的StringSerializer,继承JsonSerializer,重写serialize方法,自定义Jackson序列化器SensitiveSerializer针对String类型数据进行数据脱敏处理。

public class SensitiveSerializer extends JsonSerializer implements ContextualSerializer {
    private Sensitive.Type type;
    private int startInclude;
    private int endExclude;
    private int overlayRepeat;

    public SensitiveSerializer() {}
    public SensitiveSerializer(final Sensitive sensitive) {
        this.type = sensitive.value();
        this.startInclude = sensitive.startInclude();
        this.endExclude = sensitive.endExclude();
        this.overlayRepeat = sensitive.overlayRepeat();
    }


    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if(ObjectUtil.isEmpty(value)){
            gen.writeString(value);
            return;
        }else {
            switch (this.type) {
                case MOBILE:
                    gen.writeString(SensitiveUtil.handlerMobile(value));
                    break;
                case ID_CARD:
                    gen.writeString(SensitiveUtil.handlerIdCard(value));
                    break;
                case BANK_CARD:
                    gen.writeString(SensitiveUtil.handlerBankCard(value));
                    break;
                case CHINESE_NAME:
                    gen.writeString(SensitiveUtil.handlerUsername(value));
                    break;
                case FIXED_PHONE:
                    gen.writeString(SensitiveUtil.handlerFixedPhone(value));
                    break;
                case ADDRESS:
                    gen.writeString(SensitiveUtil.handlerAddress(value));
                    break;
                case EMAIL:
                    gen.writeString(SensitiveUtil.handlerEmail(value));
                    break;
                case CUSTOM_HIDE:
                    gen.writeString(SensitiveUtil.hide(value,startInclude,endExclude));
                    break;
                case CUSTOM_RETAIN_HIDE:
                    gen.writeString(SensitiveUtil.hide(value,startInclude,(value.length()-endExclude)));
                    break;
                case CUSTOM_OVERLAY:
                    gen.writeString(SensitiveUtil.overlay(value, StringPool.ASTERISK,overlayRepeat,startInclude,endExclude));
                    break;
                default:
                    gen.writeString(value);
            }
        }

    }

    @Override
    public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if(Objects.isNull(property)){
            return prov.getDefaultNullValueSerializer();
        }
        if(Objects.equals(property.getType().getRawClass(), String.class)){
            Sensitive sensitive = property.getAnnotation(Sensitive.class);
            if (Objects.isNull(sensitive)) {
                sensitive = property.getContextAnnotation(Sensitive.class);
            }
            if (Objects.nonNull(sensitive)) {
                return new SensitiveSerializer(sensitive);
            }
        }
        return prov.findValueSerializer(property.getType(), property);
        //Sensitive sensitive = property.getAnnotation(Sensitive.class);
        //type = sensitive.value();
        //return this;
    }
}
4. 测试使用

创建实体类Student

public class Student {

    @Sensitive(value = Sensitive.Type.CHINESE_NAME)
    private String name;

    @Sensitive(value = Sensitive.Type.ID_CARD)
    private String idCard;

    @Sensitive(value = Sensitive.Type.BANK_CARD)
    private String bankCard;

    @Sensitive(value = Sensitive.Type.FIXED_PHONE)
    private String fixedPhone;

    @Sensitive(value = Sensitive.Type.ADDRESS)
    private String address;

    @Sensitive(value = Sensitive.Type.EMAIL)
    private String email;

    @Sensitive(value = Sensitive.Type.CUSTOM_RETAIN_HIDE,startInclude = 3,endExclude = 10)
    private String remark;

    public Student() {
    }

    public String getBankCard() {
        return bankCard;
    }

    public void setBankCard(String bankCard) {
        this.bankCard = bankCard;
    }

    public String getFixedPhone() {
        return fixedPhone;
    }

    public void setFixedPhone(String fixedPhone) {
        this.fixedPhone = fixedPhone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public Student(String name, String idCard, String bankCard, String fixedPhone, String address, String email, String remark) {
        this.name = name;
        this.idCard = idCard;
        this.bankCard = bankCard;
        this.fixedPhone = fixedPhone;
        this.address = address;
        this.email = email;
        this.remark = remark;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }
}

定义接口/test/student

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/student")
    public Student getStudent(){
        Student student = new Student();
        student.setName("张三三");
        student.setIdCard("44082199612054343");
        student.setBankCard("62173300255879654448");
        student.setFixedPhone("3110026");
        student.setAddress("广东省广州市天河区");
        student.setEmail("1258398545@qq.com");
        student.setRemark("sadhaonsdoasnodnaonodsn是大祭司大祭司你");
        return student;
    }
}

浏览器请求接口/test/student,查看接口返回的数据

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1023167.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号