SpringBoot进阶教程(七十五)数据脱敏
无论对于什么业务来说,用户数据信息的安全性无疑都是非常重要的。尤其是在数字经济大火背景下,数据的安全性就显得更加重要。数据脱敏可以分为两个部分,一个是DB层面,防止DB数据泄露,暴露用户信息;一个是接口层面,有些UI展示需要数据脱敏,防止用户信息被人刷走了。
v需求背景
DB层面的脱敏今天先不讲,今天先讲讲依赖于注解的接口层面的数据脱敏,接口层面的脱敏可能最原始和简单的方法就是在每个controller输出数据时,硬性处理。但是这么做的方案,如果后续脱敏规则改了,那需要改的地方就太多了,而且很容易有遗漏的地方,造成全站脱敏规则不统一的情况。所以我们建议的是用注解的方式,可插拔性更好,随时可以更改规则,更加的灵活。
我们今天接到的需求是这样的:

页面或者接口层面的脱敏,大多也是围绕用户手机号啊、真实姓名或者地址等等展开的。
v架构设计
这里定义一个敏感字段的枚举,并设定各个字段的脱敏策略。
/**
* @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,'13555551111@126.com','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, "用户不存在");
}
}
}
v运行效果

v源码地址
https://github.com/toutouge/javademosecond/tree/master/hellolearn
作 者:请叫我头头哥
出 处:http://www.cnblogs.com/toutou/
关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
#comment_body_3242240 { display: none }
SpringBoot进阶教程(七十五)数据脱敏的更多相关文章
- SpringBoot进阶教程(七十四)整合ELK
在上一篇文章<SpringBoot进阶教程(七十三)整合elasticsearch >,已经详细介绍了关于elasticsearch的安装与使用,现在主要来看看关于ELK的定义.安装及使用 ...
- SpringBoot进阶教程(六十五)自定义注解
在上一篇文章<SpringBoot进阶教程(六十四)注解大全>中介绍了springboot的常用注解,springboot提供的注解非常的多,这些注解简化了我们的很多操作.今天主要介绍介绍 ...
- SpringBoot进阶教程(七十)SkyWalking
流行的APM(Application Performance Management工具有很多,比如Cat.Zipkin.Pinpoint.SkyWalking.优秀的监控工具还有很多,其它比如还有za ...
- SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用
在上一篇文章(<SpringBoot(二十四)整合Redis>)中,已经实现了Spring Boot对Redis的整合,既然已经讲到Cache了,今天就介绍介绍缓存注解.各家互联网产品现在 ...
- SpringBoot进阶教程(六十四)注解大全
在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...
- SpringBoot进阶教程(二十九)整合Redis 发布订阅
SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不用编程就可以向特定的接受者发送消息 (subscribers). Ra ...
- SpringBoot进阶教程(六十八)Sentinel实现限流降级
前面两篇文章nginx限流配置和SpringBoot进阶教程(六十七)RateLimiter限流,我们介绍了如何使用nginx和RateLimiter限流,这篇文章介绍另外一种限流方式---Senti ...
- SpringBoot进阶教程(七十一)详解Prometheus+Grafana
随着容器技术的迅速发展,Kubernetes已然成为大家追捧的容器集群管理系统.Prometheus作为生态圈Cloud Native Computing Foundation(简称:CNCF)中的重 ...
- SpringBoot进阶教程(六十)intellij idea project下建多个module搭建架构(上)
在 IntelliJ IDEA 中,没有类似于 Eclipse 工作空间(Workspace)的概念,而是提出了Project和Module这两个概念.多module有一个父maven工程,多个子工程 ...
- SpringBoot进阶教程(二十六)整合Redis之共享Session
集群现在越来越常见,当我们项目搭建了集群,就会产生session共享问题.因为session是保存在服务器上面的.那么解决这一问题,大致有三个方案,1.通过nginx的负载均衡其中一种ip绑定来实现( ...
随机推荐
- 【摘】python和它的装饰器
python和它的装饰器 即使你没听过装饰器,你也一定知道@staticmethod 作为函数的装饰器,你可以这样写 def mydecorator(function): def wrapped(*a ...
- Jmeter八、关联
关联的方式:1.正则2.Xpath 后置 处理器→正则表达式提取器 正则表达式:(.*) 模板$1$ 匹配数字:0代表随机,-1代表所有 缺省值为空即可
- gpio 理解
NVIC :NVIC_Init(&NVIC_Initsture); 1.NVIC只是设置某一种中断的优先级,而不是打开某种中断. 2.ppp_ITConfig():才是开/关具体某种中断使能位 ...
- Python 去掉文本内容中的\xa0字符
爬取网页时,不可避免会遇到\xa0字符串,就会发现,正则re.sub(r'\xa0', '')和字符串的replace都不管用. 通常地,我们所用的空格的ASCII码是 \x20 ,是在标准ASCII ...
- pytorch 简简单单求个值
能用张量处理就用张量,不要使用for in 跑循环,一个是容易出错,一个是比较浪费时间,应用广播机制的话去做很容易的 1.5 使用mean处理平均值 2. 在处理梯度的时候无法更改自身,因此使用的办法 ...
- 无线电(手台、APRS)
泉胜手台操作:(TG-UV2)----------------------------------------------- MR/VFO: 频率模式指示F:信道模式指示M F+MAIN: 主副频转换 ...
- == 和 equal 的区别
== 比较的是两个对象的索引是否相同: equal 比较的是两个对象内容是否相同: int a = 1;long b = 1L;a==b? 答案是 对:因为a和b指向的索引地址相同. 再例如 Stri ...
- 简单了解promise
promise是什么: JavaScript中存在很多异步操作, Promise将异步操作队列化,按照期望的顺序执行,返回 符合预期的结果.可以通过链式调用多个 Promise达到我们的目的. Pro ...
- python基础简记
pyhon 2 兼容 python 3 : 导入__future__包: 一些命名规定:以单划线开头的表示不能直接访问类属性,需要访问接口:以双划线开头的表示类的私有成员:以双划线开头和结尾的表示py ...
- w10 端口转发
场景:同局域网,将其他电脑监听映射到本地.(由于各种安全设计的定点通信) 1.添加端口转发netsh interface portproxy add v4tov4 listenport=4000 li ...