SpringBoot進階教程(七十五)資料脫敏

請叫我頭頭哥發表於2023-04-01

無論對於什麼業務來說,使用者資料資訊的安全性無疑都是非常重要的。尤其是在數字經濟大火背景下,資料的安全性就顯得更加重要。資料脫敏可以分為兩個部分,一個是DB層面,防止DB資料洩露,暴露使用者資訊;一個是介面層面,有些UI展示需要資料脫敏,防止使用者資訊被人刷走了。

v需求背景

DB層面的脫敏今天先不講,今天先講講依賴於註解的介面層面的資料脫敏,介面層面的脫敏可能最原始和簡單的方法就是在每個controller輸出資料時,硬性處理。但是這麼做的方案,如果後續脫敏規則改了,那需要改的地方就太多了,而且很容易有遺漏的地方,造成全站脫敏規則不統一的情況。所以我們建議的是用註解的方式,可插拔性更好,隨時可以更改規則,更加的靈活。

我們今天接到的需求是這樣的:

頁面或者介面層面的脫敏,大多也是圍繞使用者手機號啊、真實姓名或者地址等等展開的。

v架構設計

2.1 脫敏欄位列舉:SensitivityEnum

這裡定義一個敏感欄位的列舉,並設定各個欄位的脫敏策略。

/**
 * @Author tou tou
 * @Date 2023/1/15
 * @Des 脫敏型別及策略,不同的欄位型別適配不同的策略
 */
public enum SensitivityEnum {
    /**
     * 使用者名稱
     */
    USERNAME(s -> s.replaceAll("\\S*(\\S)", "***$1")),
    /**
     * 身份證
     */
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),
    /**
     * 手機號
     */
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
    /**
     * 地址
     */
    ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****"));


    private final Function<String, String> desensitizer;

    SensitivityEnum(Function<String, String> desensitizer) {
        this.desensitizer = desensitizer;
    }

    public Function<String, String> desensitizer() {
        return desensitizer;
    }
}
2.2 建立自定義隱私註解:Sensitivity

都說了,我們使用的是註解的方式脫敏,所以是需要宣告一個脫敏註解的,需要用到的地方,按需宣告註解即可。非常方便。

/**
 * @Author tou tou
 * @Date 2023/1/15
 * @Des
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitivitySerializer.class)
public @interface Sensitivity {
    SensitivityEnum strategy();
}
2.3 建立序列化類:SensitivitySerializer
/**
 * @Author tou tou
 * @Date 2023/1/15
 * @Des
 */
public class SensitivitySerializer extends JsonSerializer<String> implements ContextualSerializer {
    private SensitivityEnum sensitivityEnum;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(sensitivityEnum.desensitizer().apply(value));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {

        Sensitivity annotation = property.getAnnotation(Sensitivity.class);
        if (Objects.nonNull(annotation)&&Objects.equals(String.class, property.getType().getRawClass())) {
            this.sensitivityEnum = annotation.strategy();
            return this;
        }

        return prov.findValueSerializer(property.getType(), property);
    }
}
2.4 使用了@Sensitivity註解的實體類
public class UserAccountVO {
    private Integer id;

    @Sensitivity(strategy = SensitivityEnum.USERNAME)
    private String username;

    private Integer age;

    @Sensitivity(strategy = SensitivityEnum.PHONE)
    private String tel;

    private String email;

    private String account;
}
2.5 插入mysql測試資料
create table useraccount
(
id INT(11),
username NVARCHAR(25),
age INT(11),
phone bigint,
email VARCHAR(80),
account VARCHAR(20),
pwd VARCHAR(20)
);

select * from useraccount;
insert into useraccount values(1,'張老三', 22, 13555551111,'13555551111@126.com','z13555551111', '13555551111');
2.6 測試介面
/**
 * @author toutou
 * @date by 2019/07
 */
@RestController
public class UserController {

    @Autowired
    UserAccountService userAccountService;
    
    @GetMapping("/user/getuser")
    public Result getUserAccountById(@RequestParam("uid") int id){
        UserAccountVO user = userAccountService.getUserAccountById(id);
        if(user != null){
            return Result.setSuccessResult(user);
        }else{
            return Result.setErrorResult(404, "使用者不存在");
        }
    }
}

v執行效果

SpringBoot進階教程(七十五)資料脫敏

v原始碼地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn


作  者:請叫我頭頭哥
出  處:http://www.cnblogs.com/toutou/
關於作者:專注於基礎平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!

相關文章