每天积累一点,又一天总会成功
目录
背景
有的系统为保证系统数据存储安全我们系统中有些公共字段需要加密存储,在使用时读入到内存中我们需要解密。
技术方案
1、入库代码与查询时进行数据加密与解密
2、持久层使用AOP拦截根据公共参数进行加密与解密
3、自己定义Mybatis拦截器实现
技术方案选择
1、方案一代码比较耦合,主要代码比较重复
2、老系统公共参数比较乱,不适合
3、比较适合;把通过拦截器把公共参数放到 入参里面,在SQL进行解密,在入库比较单一直接在拦截器进行加密。
实现步骤
查询拦截器
@Intercepts(
{
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
}
)
public class GloableParamInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
//TODO 自己要进行的各种处理
if (!Objects.isNull(parameter)) {
if (parameter instanceof Map) {
((Map) parameter).put("secretKey", "密钥");
} else if (parameter instanceof Long) {
Long id = (Long) parameter;
Map parameters = new HashMap<>();
parameters.put("id", id);
parameters.put("secretKey", "密钥");
args[1] = parameters;
} else if (parameter instanceof Long) {
String id = (String) parameter;
Map parameters = new HashMap<>();
parameters.put("id", id);
parameters.put("secretKey", "密钥");
args[1] = parameters;
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
注意:Mybatis Xml配置中ParamType 不能配置值,不然会报错
操作拦截器
@Intercepts(
{
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
}
)
public class OPInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
if (!CommonUtils.isNullOrEmpty(args)) {
for (Object object: args) {
if (object instanceof CommonVo) {
//加密处理
CommonVo object1 = (CommonVo) object;
object1.setName(AesEncode.enCode(object1.getName()))
}
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
公共实体
public class CommonVo implements Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
配置拦截器
配置拦截器有很多种,这里我只说一种,通过代码配置
@Configuration
public class GlobalVariableConfig {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
@PostConstruct
public void addPageInterceptor() {
GloableParamInterceptor gloableParamInterceptor = new GloableParamInterceptor();
OpInterceptor opInterceptor = new OpInterceptor ();
Properties properties = new Properties();
//先把一般方式配置的属性放进去
properties.putAll(this.properties.getProperties());
//在把特殊配置放进去,由于close-conn 利用上面方式时,属性名就是 close-conn 而不是 closeConn,所以需要额外的一步
pageInterceptor.setProperties(properties);
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
sqlSessionFactory.getConfiguration().addInterceptor(gloableParamInterceptor);
sqlSessionFactory.getConfiguration().addInterceptor(insertOrUpdataInterceptor);
}
}
}
查询拦截器不生效
通过分析,发现拦截器与pagehelper定义分页拦截器有冲突,分页拦截器先调用,他在调用完成后没有往下调。
其种Mybatis中我们在集成时有这个自动加载:
groupId=com.github.pagehelper
artifactId=pagehelper-spring-boot-autoconfigure
我们定义的查询拦截器是不会生效的
问题解决
首先通过关闭自动加载配置,在入库排除加载
PageHelperAutoConfiguration通过
@SpringBootApplication(exclude = {PageHelperAutoConfiguration.class})
修改配置,拷贝 PageHelperAutoConfiguration初始化,并把我们自己加载上去
@Configuration
@EnableConfigurationProperties({PageHelperProperties.class})
public class GlobalVariableConfig {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
@Autowired
private PageHelperProperties properties;
/**
* 接受分页插件额外的属性
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = "pagehelper")
public Properties pageHelperProperties() {
return new Properties();
}
@PostConstruct
public void addPageInterceptor() {
GloableParamInterceptor gloableParamInterceptor = new GloableParamInterceptor();
PageInterceptor pageInterceptor = new PageInterceptor();
OpInterceptor opInterceptor = new OpInterceptor();
Properties properties = new Properties();
//先把一般方式配置的属性放进去
properties.putAll(pageHelperProperties());
properties.putAll(this.properties.getProperties());
//在把特殊配置放进去,由于close-conn 利用上面方式时,属性名就是 close-conn 而不是 closeConn,所以需要额外的一步
pageInterceptor.setProperties(properties);
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
sqlSessionFactory.getConfiguration().addInterceptor(pageInterceptor);
sqlSessionFactory.getConfiguration().addInterceptor(gloableParamInterceptor);
sqlSessionFactory.getConfiguration().addInterceptor(opInterceptor );
}
}
}
测试生效