场景
SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文,查询明文:
SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文,查询明文_霸道流氓气质的博客-CSDN博客
上面讲的是数据库中存储密文,查询时使用明文的脱敏方式,如果是需要数据库中存储
明文,而在查询时返回处理后的数据,比如身份证号、手机号等敏感数据,可以通过如下方式。
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
实现
1、自定义Jackson注解
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive {//脱敏策略SensitiveStrategy strategy();
}
2、指定脱敏策略,这个规则根据业务具体需求去制定,下面只做演示
import java.util.function.Function;/*** 脱敏策略,枚举类,针对不同的数据定制特定的策略*/
public enum SensitiveStrategy {/*** 用户名*/USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),/*** 身份证*/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;SensitiveStrategy(Function<String, String> desensitizer) {this.desensitizer = desensitizer;}public Function<String, String> desensitizer() {return desensitizer;}
}
3、定制JSON序列化实现
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import java.io.IOException;
import java.util.Objects;/*** 序列化注解自定义实现* JsonSerializer<String>:指定String 类型,serialize()方法用于将修改后的数据载入*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {private SensitiveStrategy strategy;@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throwsIOException {gen.writeString(strategy.desensitizer().apply(value));}/*** 获取属性上的注解属性*/@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throwsJsonMappingException {Sensitive annotation = property.getAnnotation(Sensitive.class);if (Objects.nonNull(annotation)&&Objects.equals(String.class,property.getType().getRawClass())) {this.strategy = annotation.strategy();return this;}return prov.findValueSerializer(property.getType(), property);}
}
4、新增User类,并对需要脱敏的字段添加注解,并指定脱敏策略
import com.badao.demo.sensitive.Sensitive;
import com.badao.demo.sensitive.SensitiveStrategy;
import lombok.Data;
import java.io.Serializable;@Data
public class User implements Serializable {private static final long serialVersionUID = -5514139686858156155L;private Integer id;private Integer userId;@Sensitive(strategy = SensitiveStrategy.USERNAME)private String name;private Integer age;}
5、编写controller进行测试
@RequestMapping("user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("save")public String save() {User user = new User();user.setUserId(new Random().nextInt( 1000 ) + 1);user.setName("badao"+user.getUserId());user.setAge(new Random().nextInt( 80 ) + 1);userService.insert(user);return "save success";}@RequestMapping("select")public User select() {List<User> all = userService.findAll();return all.size()>0?all.get(0):new User();}
}
测试效果