实现数据脱敏
在实际开发中,我们经常会遇到需要对一些敏感信息进行脱敏处理的情况,如手机号、身份证号、银行卡号等。而 MyBatis 插件和注解就可以帮助我们实现对这些信息的脱敏。
以手机号为例,我们可以使用 MyBatis 插件和注解来实现对手机号的脱敏。具体步骤如下:
- 自定义一个Interceptor,在其中重写intercept()方法,实现对 SQL 语句中手机号的脱敏处理。
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class PhoneInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获取当前的StatementHandler
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
// 获取MappedStatement对象
MappedStatement mappedStatement = (MappedStatement) ReflectionUtil.getFieldValue(statementHandler, "mappedStatement");
// 获取SQL语句类型
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
// 如果是查询操作,则不做处理
if (sqlCommandType == SqlCommandType.SELECT) {
return invocation.proceed();
}
// 获取SQL语句
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
// 如果SQL语句中不包含手机号,则不做处理
if (!sql.contains("phone") && !sql.contains("PHONE")) {
return invocation.proceed();
}
// 获取参数
Object parameterObject = boundSql.getParameterObject();
if (parameterObject == null) {
return invocation.proceed();
}
// 获取手机号参数
String phone = null;
if (parameterObject instanceof String) {
phone = (String) parameterObject;
} else if (parameterObject instanceof Map) {
Map<String, Object> paramMap = (Map<String, Object>) parameterObject;
for (Object value : paramMap.values()) {
if (value instanceof String) {
phone = (String) value;
break;
}
}
} else if (parameterObject instanceof Object[]) {
Object[] objects = (Object[]) parameterObject;
for (Object obj : objects) {
if (obj instanceof String) {
phone = (String) obj;
break;
}
}
} else {
Field[] fields = parameterObject.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object fieldValue = field.get(parameterObject);
if (fieldValue instanceof String && field.getName().toLowerCase().contains("phone")) {
phone = (String) fieldValue;
break;
}
}
}
// 对手机号进行脱敏处理
String desensitizedPhone = DesensitizerUtil.desensitizePhone(phone);
// 替换原SQL语句中的手机号
sql = sql.replaceAll(phone, desensitizedPhone);
// 设置新的SQL语句
ReflectionUtil.setFieldValue(boundSql, "sql", sql);
return invocation.proceed();
}
}
- 使用注解将自定义的Interceptor绑定到Mapper接口方法上。
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class PhoneInterceptor implements Interceptor {
// 省略代码...
}
- 在Mapper接口方法中使用注解标注需要进行脱敏的手机号参数
public interface UserMapper {
@Select("select * from user where phone = #{phone}")
User findUserByPhone(@DesensitizePhone @Param("phone") String phone);
}
其中,@DesensitizePhone注解是自定义的一个注解,用于标注需要进行脱敏处理的手机号参数。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface DesensitizePhone {
}
- 实现对手机号的脱敏处理。
public class DesensitizerUtil {
public static String desensitizePhone(String phone) {
if (StringUtils.isBlank(phone)) {
return "";
}
return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})");
- 将Interceptor注册到MyBatis中。
在MyBatis的配置文件中,通过以下方式将自定义的Interceptor注册到MyBatis中。
configuration>
<plugins>
<plugin interceptor="com.example.PhoneInterceptor"/>
</plugins>
</configuration>
至此,我们就完成了使用MyBatis插件和注解轻松实现数据脱敏的全过程。接下来,我们来对这个实现过程进行一下总结。
总结
通过本文的介绍,我们可以看到,使用MyBatis插件和注解轻松实现数据脱敏的过程是非常简单和快速的。具体来说,我们可以通过自定义一个Interceptor来实现对SQL语句中手机号的脱敏处理,然后通过将Interceptor绑定到Mapper接口方法上,再结合使用自定义的注解来标注需要进行脱敏处理的手机号参数,就可以在MyBatis的使用过程中自动完成数据脱敏的操作。