無論對於什麼業務來說,使用者資料資訊的安全性無疑都是非常重要的。尤其是在數位經濟大火背景下,資料的安全性就顯得更加重要。資料脫敏可以分為兩個部分,一個是DB層面,防止DB資料洩露,暴露使用者資訊;一個是介面層面,有些UI展示需要資料脫敏,防止使用者資訊被人刷走了。
DB層面的脫敏今天先不講,今天先講講依賴於註解的介面層面的資料脫敏,介面層面的脫敏可能最原始和簡單的方法就是在每個controller輸出資料時,硬性處理。但是這麼做的方案,如果後續脫敏規則改了,那需要改的地方就太多了,而且很容易有遺漏的地方,造成全站脫敏規則不統一的情況。所以我們建議的是用註解的方式,可插拔性更好,隨時可以更改規則,更加的靈活。
我們今天接到的需求是這樣的:
頁面或者介面層面的脫敏,大多也是圍繞使用者手機號啊、真實姓名或者地址等等展開的。
這裡定義一個敏感欄位的列舉,並設定各個欄位的脫敏策略。
/** * @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; } }
都說了,我們使用的是註解的方式脫敏,所以是需要宣告一個脫敏註解的,需要用到的地方,按需宣告註解即可。非常方便。
/** * @Author tou tou * @Date 2023/1/15 * @Des */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JacksonAnnotationsInside @JsonSerialize(using = SensitivitySerializer.class) public @interface Sensitivity { SensitivityEnum strategy(); }
/** * @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); } }
@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; }
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,'[email protected]','z13555551111', '13555551111');
/** * @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, "使用者不存在"); } } }
https://github.com/toutouge/javademosecond/tree/master/hellolearn
作 者:請叫我頭頭哥
出 處:http://www.cnblogs.com/toutou/
關於作者:專注於基礎平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!