提交 c7164297 authored 作者:  狄熙卜's avatar 狄熙卜

支持注解加解密配置

上级 3e47aa46
...@@ -66,6 +66,11 @@ ...@@ -66,6 +66,11 @@
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package cn.gtmap.bdcdj.core.encrypt; package cn.gtmap.bdcdj.core.encrypt;
import cn.gtmap.bdcdj.core.encrypt.annotation.Encrypt;
import cn.gtmap.bdcdj.core.encrypt.annotation.Encrypts;
import cn.gtmap.bdcdj.core.encrypt.config.BaseConfig; import cn.gtmap.bdcdj.core.encrypt.config.BaseConfig;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.signers.ECNRSigner;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultText; import org.dom4j.tree.DefaultText;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class DbEncryptXmlConfig { public class DbEncryptXmlConfig {
private Resource configUrl; private Resource configUrl;
...@@ -50,6 +61,17 @@ public class DbEncryptXmlConfig { ...@@ -50,6 +61,17 @@ public class DbEncryptXmlConfig {
private String interfaceSm2EncodeKey;//接口加解密时,sm2加密的公钥 private String interfaceSm2EncodeKey;//接口加解密时,sm2加密的公钥
private List<String> baseConfigOptions; private List<String> baseConfigOptions;
//注解加解密相关配置,配置不出现于CryptProperties对象中,在此类中处理后存在其他属性中
//注解加解密总开关
private boolean annoEnable;
//生效的注解分组名称列表
private List<String> annoGroupNames;
//实体类注解扫描包
private String annoEntityPackage;
//sql方法注解扫描包
private String annoSqlPackage;
public void setBaseConfig(List<BaseConfig> baseConfig) { public void setBaseConfig(List<BaseConfig> baseConfig) {
this.baseConfig = baseConfig; this.baseConfig = baseConfig;
} }
...@@ -493,4 +515,237 @@ public class DbEncryptXmlConfig { ...@@ -493,4 +515,237 @@ public class DbEncryptXmlConfig {
} }
} }
} }
//对注解加解密的处理
public boolean isAnnoEnable() {
return getBooleanField("AnnoEnable");
}
public void setAnnoEnable(boolean annoEnable) {
this.annoEnable = annoEnable;
}
public List<String> getAnnoGroupNames() {
if(annoGroupNames == null){
annoGroupNames = getArrFields("AnnoGroupNames");
}
return annoGroupNames;
}
public void setAnnoGroupNames(List<String> annoGroupNames) {
this.annoGroupNames = annoGroupNames;
}
public String getAnnoEntityPackage() {
if(StringUtils.isBlank(annoEntityPackage)){
annoEntityPackage = getField("AnnoEntityPackage");
}
return annoEntityPackage;
}
public void setAnnoEntityPackage(String annoEntityPackage) {
this.annoEntityPackage = annoEntityPackage;
}
public String getAnnoSqlPackage() {
if(StringUtils.isBlank(annoSqlPackage)){
annoSqlPackage = getField("AnnoSqlPackage");
}
return annoSqlPackage;
}
public void setAnnoSqlPackage(String annoSqlPackage) {
this.annoSqlPackage = annoSqlPackage;
}
public void addAnnotationConfigFileds() {
//获取注解加解密总开关
if(!isAnnoEnable()){
return;
}
List<String> annoGroupNames = getAnnoGroupNames();
if(CollectionUtils.isEmpty(annoGroupNames)){
return;
}
//获取实体中的注解
String annoEntityPackage = getAnnoEntityPackage();
if(StringUtils.isNotBlank(annoEntityPackage)) {
Reflections ref = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage(annoEntityPackage))
.addScanners(new FieldAnnotationsScanner()));
Set<Field> encryptAnnoFields = ref.getFieldsAnnotatedWith(Encrypt.class);
List<Map> annoEntityFileds = new ArrayList<Map>();
if (CollectionUtils.isNotEmpty(encryptAnnoFields)) {
for (Field field : encryptAnnoFields) {
Encrypt annotation = field.getAnnotation(Encrypt.class);
if (annotation == null || !annoGroupNames.contains(annotation.group())) {//没有值,跳过;组别不对 跳过
continue;
}
Class<?> declaringClass = field.getDeclaringClass();
if (declaringClass == null) {
continue;
}
String className = declaringClass.getName();
Map map = new HashMap<String, Object>();
map.put("entity", className);
map.put("field", field.getName());
annoEntityFileds.add(map);
}
}
if (CollectionUtils.isNotEmpty(annoEntityFileds)) {
if (CollectionUtils.isEmpty(entityFileds)) {
entityFileds = new ArrayList<Map>();
}
entityFileds.addAll(annoEntityFileds);
}
}
//获取sql方法上的注解
String annoSqlPackage = getAnnoSqlPackage();
if(StringUtils.isBlank(annoSqlPackage)){
return;
}
Reflections ref = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage(annoSqlPackage))
.addScanners(new MethodAnnotationsScanner()));
//先获取Encrypt注解
Set<Method> enctyptMethods = ref.getMethodsAnnotatedWith(Encrypt.class);
//再获取Encrypts注解
Set<Method> enctyptArrMethods = ref.getMethodsAnnotatedWith(Encrypts.class);
if(!CollectionUtils.isNotEmpty(enctyptMethods) && !CollectionUtils.isNotEmpty(enctyptArrMethods)){//没有注解 返回
return;
}
//sql加解密字段
List<Map> annoSqlFileds = new ArrayList<Map>();
//sql仅加密字段
List<Map> annoSqlEncryptFileds = new ArrayList<Map>();
//sql仅解密字段
List<Map> annoSqlDecryptFileds = new ArrayList<Map>();
//sql参数为单独的string,对参数加密(等价于注解)
List<String> annoSqlSingleEncryptFileds = new ArrayList<String>();
//sql返回值为单独的string,对返回值加密(等价于注解)
List<String> annoSqlSingleDecryptFileds = new ArrayList<String>();
//处理方法上的Encrypt注解
if(CollectionUtils.isNotEmpty(enctyptMethods)){
for (Method method : enctyptMethods) {
Encrypt annotation = method.getAnnotation(Encrypt.class);
getFieldsFromAnno(annoSqlFileds,annoSqlEncryptFileds,annoSqlDecryptFileds,annoSqlSingleEncryptFileds,
annoSqlSingleDecryptFileds,method,annotation);
}
}
//处理方法上的Encrypts注解
if(CollectionUtils.isNotEmpty(enctyptArrMethods)){
for (Method method : enctyptArrMethods) {
Encrypts annotation = method.getAnnotation(Encrypts.class);
Encrypt[] value = annotation.value();
if(value != null && value.length > 0){
for (Encrypt encrypt : value) {
getFieldsFromAnno(annoSqlFileds,annoSqlEncryptFileds,annoSqlDecryptFileds,annoSqlSingleEncryptFileds,
annoSqlSingleDecryptFileds,method,encrypt);
}
}
}
}
//预置的sql加解密字段(正向配置)
if(CollectionUtils.isNotEmpty(annoSqlFileds)){
if(CollectionUtils.isEmpty(sqlFileds)){
sqlFileds = new ArrayList<Map>();
}
sqlFileds.addAll(annoSqlFileds);
}
//预置的sql加密字段(正向配置)
if(CollectionUtils.isNotEmpty(annoSqlEncryptFileds)){
if(CollectionUtils.isEmpty(sqlEncryptFileds)){
sqlEncryptFileds = new ArrayList<Map>();
}
sqlEncryptFileds.addAll(annoSqlEncryptFileds);
}
//预置的sql解密字段(正向配置)
if(CollectionUtils.isNotEmpty(annoSqlDecryptFileds)){
if(CollectionUtils.isEmpty(sqlDecryptFileds)){
sqlDecryptFileds = new ArrayList<Map>();
}
sqlDecryptFileds.addAll(annoSqlDecryptFileds);
}
//单一string作为参数加密(正向配置)
if(CollectionUtils.isNotEmpty(annoSqlSingleEncryptFileds)){
if(CollectionUtils.isEmpty(sqlSingleEncryptFileds)){
sqlSingleEncryptFileds = new ArrayList<String>();
}
sqlSingleEncryptFileds.addAll(annoSqlSingleEncryptFileds);
}
//单一string作为返回值解密(正向配置)
if(CollectionUtils.isNotEmpty(annoSqlSingleDecryptFileds)){
if(CollectionUtils.isEmpty(sqlSingleDecryptFileds)){
sqlSingleDecryptFileds = new ArrayList<String>();
}
sqlSingleDecryptFileds.addAll(annoSqlSingleDecryptFileds);
}
}
/**
* 同时提供方法和注解参数,便于代码的复用
* @param annoSqlFileds
* @param annoSqlEncryptFileds
* @param annoSqlDecryptFileds
* @param annoSqlSingleEncryptFileds
* @param annoSqlSingleDecryptFileds
* @param method
* @param annotation
*/
private void getFieldsFromAnno(List<Map> annoSqlFileds,List<Map> annoSqlEncryptFileds,List<Map> annoSqlDecryptFileds,
List<String> annoSqlSingleEncryptFileds,List<String> annoSqlSingleDecryptFileds,Method method,Encrypt annotation){
if(annotation == null || !annoGroupNames.contains(annotation.group())){
return;
}
String className = method.getDeclaringClass().getName();
String fileds = annotation.fileds();//注解的加解密属性处理
if(StringUtils.isNotBlank(fileds)){
String[] split = fileds.split(",");
if(split != null && split.length > 0){
for (String s : split) {
Map sqlFiledMap = new HashMap<String,Object>();
sqlFiledMap.put("mapid",className+"."+method.getName());
sqlFiledMap.put("field",s);
annoSqlFileds.add(sqlFiledMap);
}
}
}
String encodeFileds = annotation.encodeFileds();//注解的加密属性处理
if(StringUtils.isNotBlank(encodeFileds)){
String[] split = encodeFileds.split(",");
if(split != null && split.length > 0){
for (String s : split) {
Map sqlEncryptFiledMap = new HashMap<String, Object>();
sqlEncryptFiledMap.put("mapid", className+"."+method.getName());
sqlEncryptFiledMap.put("field", s);
annoSqlEncryptFileds.add(sqlEncryptFiledMap);
}
}
}
String decodeFileds = annotation.decodeFileds();//注解的解密属性处理
if(StringUtils.isNotBlank(decodeFileds)){
String[] split = decodeFileds.split(",");
if(split != null && split.length > 0) {
for (String s : split) {
Map sqlDecryptFiledMap = new HashMap<String, Object>();
sqlDecryptFiledMap.put("mapid", className+"."+method.getName());
sqlDecryptFiledMap.put("field", s);
annoSqlDecryptFileds.add(sqlDecryptFiledMap);
}
}
}
boolean singleEncrypt = annotation.singleEncryptFileds();//注解的仅一个参数加密属性
if(singleEncrypt){
annoSqlSingleEncryptFileds.add(className+"."+method.getName());
}
boolean singleDecrypt = annotation.singleDecryptFileds();//注解的仅有要给返回值解密属性
if(singleDecrypt){
annoSqlSingleDecryptFileds.add(className+"."+method.getName());
}
}
} }
package cn.gtmap.bdcdj.core.encrypt; package cn.gtmap.bdcdj.core.encrypt;
import cn.gtmap.bdcdj.core.encrypt.annotation.Encrypt;
import cn.gtmap.bdcdj.core.encrypt.executor.CryptType; import cn.gtmap.bdcdj.core.encrypt.executor.CryptType;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.Executor;
...@@ -12,10 +13,17 @@ import org.apache.ibatis.plugin.Plugin; ...@@ -12,10 +13,17 @@ import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.RowBounds;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@Intercepts({@Signature( @Intercepts({@Signature(
...@@ -127,6 +135,8 @@ public class EncryptInterceptor implements Interceptor { ...@@ -127,6 +135,8 @@ public class EncryptInterceptor implements Interceptor {
dbEncryptXmlConfig.getSqlSingleDecryptFileds(); dbEncryptXmlConfig.getSqlSingleDecryptFileds();
//添加预置的字段 //添加预置的字段
dbEncryptXmlConfig.addBaseConfigFileds(); dbEncryptXmlConfig.addBaseConfigFileds();
//根据注解获取加解密配置
dbEncryptXmlConfig.addAnnotationConfigFileds();
this.cryptProperties.setGlobalEnableFields(dbEncryptXmlConfig.getGlobalEnableFields()); this.cryptProperties.setGlobalEnableFields(dbEncryptXmlConfig.getGlobalEnableFields());
this.cryptProperties.setGlobalDisableMapFields(dbEncryptXmlConfig.getGlobalDisableMapFields()); this.cryptProperties.setGlobalDisableMapFields(dbEncryptXmlConfig.getGlobalDisableMapFields());
this.cryptProperties.setGlobalDisableEntityFields(dbEncryptXmlConfig.getGlobalDisableEntityFields()); this.cryptProperties.setGlobalDisableEntityFields(dbEncryptXmlConfig.getGlobalDisableEntityFields());
......
package cn.gtmap.bdcdj.core.encrypt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD})//方法和字段都可以使用
public @interface Encrypt {
//分组 分组之后才能进行加解密
String group();
//方法上使用的字段 对sql中的字段进行加解密
String fileds() default "";
//方法上使用的字段 对sql中入参的字段进行加密
String encodeFileds() default "";
//方法上使用的字段 对sql中返回值的字段进行解密
String decodeFileds() default "";
//方法上使用的字段 在只有一个参数时加密
boolean singleEncryptFileds() default false;
//方法上使用的字段 在只有一个参数时解密
boolean singleDecryptFileds() default false;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论