@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class MybatisInterceptor implements Interceptor {}
mybatis拦截的几个点就是执行sql需要用到的几个主要对象,主要是Executor,StatementHandler,ParamerHandler,ResultSetHandler,
StatementHandler是最常用的拦截对象。
type为mybatis执行sql的主要对象,
method是拦截对象中的指定方法,
args是拦截方法的行参。
这里是拦截Executor接口中的update,query方法,query重载的方法。
其实可以直接拦截StatementHandler中的prepare方法,由于update,query方法都需要prepare准备参数,所以拦截这个prepare就相当于拦截了StatementHandler中的update和query。
interceptor
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
default Object plugin(Object target) {
// 把拦截目标继续向下传递,可能存在多个Interceptor
return Plugin.wrap(target, this);
}
default void setProperties(Properties properties) {
//获取interceptor的配置,配置文件配置
// NOP
}
}
ms中使用interceptor
用户密码脱敏
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class UserDesensitizationInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object returnValue = invocation.proceed();
Object result = returnValue;
if (returnValue instanceof ArrayList<?>) {
List<Object> list = new ArrayList<>();
boolean isDecrypted = false;
for (Object val : (ArrayList<?>) returnValue) {
if (val instanceof User) {
isDecrypted = true;
((User) val).setPassword(null);
list.add(val);
}
}
if (isDecrypted) {
result = list;
}
} else {
if (result instanceof User) {
((User) result).setPassword(null);
}
}
return result;
}
}
对某些配置字段加解密(指定加解密的类和对应的方法)
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class MybatisInterceptor implements Interceptor {
项目启动时配置要加密的属性
@Configuration
public class DatabaseConfig {
@Bean
public MybatisInterceptor dbInterceptor() {
MybatisInterceptor interceptor = new MybatisInterceptor();
List<MybatisInterceptorConfig> configList = new ArrayList<>();
configList.add(new MybatisInterceptorConfig(FileContent.class, "file", CompressUtils.class, "zip", "unzip"));
configList.add(new MybatisInterceptorConfig(TestResource.class, "configuration"));
configList.add(new MybatisInterceptorConfig(AuthSource.class, "configuration"));
configList.add(new MybatisInterceptorConfig(LoadTestReportLog.class, "content", CompressUtils.class, "zipString", "unzipString"));
interceptor.setInterceptorConfigList(configList);
return interceptor;
}
}
主要拦截update,query方法,
如果是query方法,判断返回值是否有配置的类,有的话调用配置的解密类的解密方法,然后返回。
如果是update方法,判断参数中是否有配置的类,如果有获取需要加密的属性,调用加密方法后执行update方法。
具体代码可以参考github.com/metersphere…