Java敏感数据入参出参时自定义加解密注解

应用场景

数据库中,身份证、手机号等隐私数据密文存储,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;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要实现 AOP 自定义注解获取实体参,可以按照以下步骤进行: 1. 定义注解:定义一个注解,用于标记需要被 AOP 拦截的方法。 2. 编写切面:编写一个切面,用于拦截被注解标记的方法,并获取方法的参数。 3. 获取实体参:在切面中获取方法的参数,通过反射的方式获得实体参。 下面是一个示例代码,假设我们需要获取被 @LogAnnotation 注解标记的方法的实体参: 定义注解: ```java @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogAnnotation { String value() default ""; } ``` 编写切面: ```java @Component @Aspect public class LogAspect { @Around("@annotation(com.example.demo.annotation.LogAnnotation)") public Object around(ProceedingJoinPoint pjp) throws Throwable { // 获取方法参数 Object[] args = pjp.getArgs(); // 判断参数是否为实体类 for (Object arg : args) { if (arg instanceof BaseEntity) { // 获取实体参 BaseEntity entity = (BaseEntity) arg; // TODO: 处理实体参 } } // 执行方法 Object result = pjp.proceed(); return result; } } ``` 在上面的代码中,我们使用 @Around 注解标记了 around 方法,并指定了切点表达式 @annotation(com.example.demo.annotation.LogAnnotation),表示拦截被 @LogAnnotation 注解标记的方法。在 around 方法中,通过 ProceedingJoinPoint 对象获取方法的参数,然后判断参数是否为实体类,如果是实体类,则获取实体参,进行处理。 注意,在获取实体参时,我们使用了 instanceof 判断参数是否为实体类,因此需要保证实体类继承了一个 BaseEntity 类或接口,否则无法判断参数是否为实体类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值