应用场景
数据库中,身份证、手机号等隐私数据密文存储,Java返回数据给前端时需要解密,前端查询传入参数时,需要将数据加密,否则匹配不到数据库中存储的密文数据。
解决方案
自定义序列化解密注解,在返回给前端时,对数据解密。自定义反序列化加密注解,前端传参时,对数据加密。
加密注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonDeserialize(using = EncryptDeserializer.class)
public @interface Encrypt {
}
加密反序列化器
public class EncryptDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value = jsonParser.getValueAsString();
if (StringUtils.isNotBlank(value)) {
if (ReUtil.contains(ReConstant.ID_CARD, value) || ReUtil.contains(ReConstant.MOBILE, value)) {
return PasswordUtil.encrypt(value);
}
}
return value;
}
}
正则常量表达式常量类
public class ReConstant {
/**
* 身份证号码正则表达式
*/
public static final String ID_CARD = "^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$";
/**
* 手机号码正则表达式
*/
public static final String MOBILE = "^1[3-9]\\d{9}$";
/**
* 固定电话正则表达式
*/
public static final String FIXED_PHONE = "^0\\d{2,3}-?\\d{7,8}$";
/**
* 邮箱正则表达式
*/
public static final String EMAIL = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
}
解密注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DecryptSerializer.class)
public @interface Decrypt {
}
解密序列化器
@NoArgsConstructor
@AllArgsConstructor
public class DecryptSerializer extends JsonSerializer<String> implements ContextualSerializer {
private Decrypt decrypt;
@Override
public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(decrypt(s));
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
Decrypt decrypt = beanProperty.getAnnotation(Decrypt.class);
if (decrypt == null) {
decrypt = beanProperty.getContextAnnotation(Decrypt.class);
}
if (decrypt != null) {
return new DecryptSerializer(decrypt);
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
private String decrypt(String s) {
if (StrUtil.isNotBlank(s)) {
String value = PasswordUtil.decrypt(s);
// 正则表达式判断是否为身份证或手机号
if (ReUtil.contains(ReConstant.ID_CARD, value) || ReUtil.contains(ReConstant.MOBILE, value)) {
return value;
}
}
return s;
}
}
返回给前端的对象
@ApiModelProperty(value = "证件号码")
@Encrypt
private String idcard;
@ApiModelProperty(value = "联系电话")
@Encrypt
private String tel;
编辑数据时,需要将身份证、手机号解密
@ApiModelProperty(value = "证件号码")
@Decrypt
private String idcard;
@ApiModelProperty(value = "联系电话")
@Decrypt
private String tel;