AOP实现注解式脱敏数据明文查询

最近又遇到了脱敏数据查询相关的问题,常规的脱敏数据比如用户身份证将中间位数抹去后加入数据库,那么查询时需要手动调用就比较麻烦,不过可以使用自定义注解,利用AOP解析后在切面将数据加密再作为参数注入运行,实现非入侵的脱敏数据明文查询。简单记录一下。

情境和思路

用户身份证脱敏,保留前四位和后八位,其余转换为×符号存入数据库。利用aop在方法执行的切面将注解修饰的方法中对应的参数进行加密后注入,就能实现脱敏数据的明文搜索,而不用手动调工具类了。

实现

用户

简单的用户信息,code为身份证。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String code;
    private String name;
    private byte sex;
}

Mapper

简单的搜索接口。

@Mapper
public interface UserMapper {
    @Select("select * from user where code = #{code}")
    public User findUserByCode(String code);
}

加密工具类

将加密类型也作为参数,适应不同情况。

public class EncryptionUtil {

    public final static String SELF_CODE = "self_code";

    // 加密
    public static String encrypt(String str, String type){
        if (SELF_CODE.equals(type)) {// 身份证前四位加上后六位
            return str.substring(0, 4) + "xxxxxxxx" + str.substring(str.length() - 6);
        }
        return null;
    }
}

加密注解

@Encrypt注解,包含两个成员,indexes数组存放需要加密的参数序号,types存放加密类型。

// 自动加密注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Encrypt {
    // 记录需要加密的参数位置
    int[] indexes();
    // 记录加密对像的type
    String[] types();
}

Aop切面处理类

关键逻辑类,使用around方法和ProceedingJoinPoint对象将获取对应切面方法的注解和参数信息,对参数进行加密处理后注入。

@Component
@Aspect
public class EncryptAspect {
    @Pointcut("execution(* com.huiluczP.controller.UserController.*(..)) && @annotation(com.huiluczP.annotation.Encrypt)")

    private void point() {

    }

    @Around("point()")
    // 环绕aop,获取切面方法对应的annotation
    private Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 得到方法执行所需的参数
        Object[] args = pjp.getArgs();
        Encrypt encryptParam = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(Encrypt.class);

        // 获取需要加密的参数位置和加密类型
        int[] indexes = encryptParam.indexes();
        String[] types = encryptParam.types();

        // 对参数进行处理
        for(int i=0;i<indexes.length;i++){
            int index = indexes[i];
            args[index] = EncryptionUtil.encrypt((String)args[index], types[i]);
        }
        return pjp.proceed(args);
    }
}

这边利用execution(* com.huiluczP.controller.UserController.*(..)) && @annotation(com.huiluczP.annotation.Encrypt)将UserController中持有@Encrypt注解的所有方法都归入切面。

UserController

传入明文对象进行脱敏数据的查询。在注解中定义了加密参数位置和类型。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserMapper userMapper;

    @RequestMapping("/findByCode")
    @ResponseBody
    // 自动加密注解
    @Encrypt(indexes = {0}, types = {EncryptionUtil.SELF_CODE})
    public String findUser(String code){
        User user = userMapper.findUserByCode(code);
        return JSONObject.toJSONString(user);
    }
}

演示

成功进行了查询。AOP实现注解式脱敏数据明文查询_第1张图片

总结

简单的Aop应用,来解决脱敏数据明文查询的代码冗余问题,面向切面确实蛮方便的,就是切面定义表达式比较难写。感兴趣就看看吧。

你可能感兴趣的:(spring,java,java,springboot,spring)