Commit 06d9b778 by 郑冰晶

数据库加密组件

parent 1db65304
package com.secoo.mall.datasource.security.demo.config;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.fastjson.JSON;
import com.secoo.mall.datasource.bean.MatrixDataSource;
import com.secoo.mall.datasource.security.filter.SecurityFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
@Slf4j
@Configuration
@EnableConfigurationProperties(DataSourceSecurityProperties.class)
public class DataSourceSecurityAutoConfiguration implements ApplicationContextAware, SmartInitializingSingleton {
private static Logger logger = LoggerFactory.getLogger(DataSourceSecurityAutoConfiguration.class);
private ConfigurableApplicationContext applicationContext;
private DataSourceSecurityProperties properties;
DataSourceSecurityAutoConfiguration(DataSourceSecurityProperties properties){
this.properties = properties;
}
@Override
public void afterSingletonsInstantiated() {
log.debug(">>>>>>>>>>>>>"+JSON.toJSONString(properties));
if(properties == null || properties.getSecurityRules() == null || properties.getSecurityRules().size() == 0){
// throw new RuntimeException("DataSourceSecurityProperties is null!");
return;
}
Map<String,Map<String,Map<String,String>>> dbRules = properties.getSecurityRules().get("securityRules");
Map<String, DataSource> dataSourceBeans = this.applicationContext.getBeansOfType(DataSource.class);
dataSourceBeans.forEach(new BiConsumer<String, DataSource>() {
@Override
public void accept(String dataSourceName, DataSource dataSource) {
dbRules.forEach(new BiConsumer<String, Map<String, Map<String, String>>>() {
@Override
public void accept(String db, Map<String, Map<String, String>> dbRule) {
List<DruidDataSource> druidDataSources = new ArrayList<>();
if(dataSource instanceof DruidDataSource){
druidDataSources.add((DruidDataSource) dataSource);
}else if(dataSource instanceof MatrixDataSource){
druidDataSources.add((DruidDataSource) ((MatrixDataSource) dataSource).getTargetDataSource(((MatrixDataSource) dataSource).getDsName()));
}else if(dataSource instanceof ShardingDataSource){
((ShardingDataSource) dataSource).getDataSourceMap().forEach(new BiConsumer<String, DataSource>() {
@Override
public void accept(String innerDataSourceName, DataSource innerDataSource) {
druidDataSources.add((DruidDataSource) innerDataSource);
}
});
}
if(druidDataSources.isEmpty()){
logger.warn("dataSource type is not support!");
return;
}
druidDataSources.forEach(druidDataSource -> {
if(druidDataSource.getDbType().equalsIgnoreCase(JdbcConstants.MYSQL)){
SecurityFilter securityFilter = new SecurityFilter();
// TODO init rule config
druidDataSource.setProxyFilters(new ArrayList<Filter>(){{add(securityFilter);}});
}else{
logger.warn("database type({}) is not support!",druidDataSource.getDbType());
}
});
}
});
}
});
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
}
package com.secoo.mall.datasource.security.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Map;
@ConfigurationProperties(prefix = DataSourceSecurityProperties.PREFIX)
public class DataSourceSecurityProperties {
public static final String PREFIX = "spring.datasource.security";
/**
* 加解密规则
*/
private Map<String, Map<String,Map<String,Map<String,String>>>> securityRules;
public Map<String, Map<String, Map<String, Map<String,String>>>> getSecurityRules() {
return securityRules;
}
public void setSecurityRules(Map<String, Map<String, Map<String, Map<String,String>>>> securityRules) {
this.securityRules = securityRules;
}
}
...@@ -5,10 +5,12 @@ import com.secoo.mall.datasource.security.demo.bean.PriceRuleTaskCriteria; ...@@ -5,10 +5,12 @@ import com.secoo.mall.datasource.security.demo.bean.PriceRuleTaskCriteria;
import com.secoo.mall.datasource.security.demo.dao.entity.PriceRuleTask; import com.secoo.mall.datasource.security.demo.dao.entity.PriceRuleTask;
import com.secoo.mall.datasource.security.demo.dao.mapper.PriceRuleTaskMapper; import com.secoo.mall.datasource.security.demo.dao.mapper.PriceRuleTaskMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
...@@ -19,24 +21,55 @@ public class TestController { ...@@ -19,24 +21,55 @@ public class TestController {
private PriceRuleTaskMapper priceRuleTaskMapper; private PriceRuleTaskMapper priceRuleTaskMapper;
@RequestMapping("select") @RequestMapping("select")
public String select(Long id,String creator) { public String select(Long id,String plainText) {
PriceRuleTaskCriteria priceRuleTaskCriteria = new PriceRuleTaskCriteria(); PriceRuleTaskCriteria priceRuleTaskCriteria = new PriceRuleTaskCriteria();
priceRuleTaskCriteria.setId(id); if(id != null){
priceRuleTaskCriteria.setCreator(creator); priceRuleTaskCriteria.setId(id);
}
if(plainText != null){
priceRuleTaskCriteria.setCreator(plainText);
}
priceRuleTaskCriteria.setPageSize(1); priceRuleTaskCriteria.setPageSize(1);
List<PriceRuleTask> priceRuleTasks = this.priceRuleTaskMapper.queryPriceRuleTaskList(priceRuleTaskCriteria); List<PriceRuleTask> priceRuleTasks = this.priceRuleTaskMapper.queryPriceRuleTaskList(priceRuleTaskCriteria);
String data = JSON.toJSONString(priceRuleTasks); String data = JSON.toJSONString(priceRuleTasks);
log.debug(">>>>>>>>>>>>{}", data); log.debug("data={}", data);
return new String(data); return data;
}
@RequestMapping("insert")
public String insert() {
PriceRuleTask insertPriceRuleTask = new PriceRuleTask();
insertPriceRuleTask.setBrandId(5L);
insertPriceRuleTask.setTaskId("");
insertPriceRuleTask.setMergeTaskId("");
insertPriceRuleTask.setTaskType(1);
insertPriceRuleTask.setTaskStatus(0);
insertPriceRuleTask.setTriggerType(1);
insertPriceRuleTask.setCheckStatus(0);
insertPriceRuleTask.setCheckPointDate(new Date());
insertPriceRuleTask.setPushStatus(0);
insertPriceRuleTask.setEuropePushStatus(0);
insertPriceRuleTask.setRemark("加密测试");
insertPriceRuleTask.setShardNo(0);
insertPriceRuleTask.setCreator(String.valueOf(RandomUtils.nextInt(0,1000)));
insertPriceRuleTask.setCreatorId(0L);
insertPriceRuleTask.setCreateDate(new Date());
insertPriceRuleTask.setModifier("");
insertPriceRuleTask.setModifierId(0L);
insertPriceRuleTask.setModifyDate(new Date());
insertPriceRuleTask.setVersion(0L);
int rows = this.priceRuleTaskMapper.insertSelective(insertPriceRuleTask);
log.debug("id={}", insertPriceRuleTask.getId());
return String.valueOf("id="+insertPriceRuleTask.getId());
} }
@RequestMapping("update") @RequestMapping("update")
public String update(Long id,String creator) { public String update(Long id,String plainText) {
PriceRuleTask priceRuleTask = new PriceRuleTask(); PriceRuleTask updatePriceRuleTask = new PriceRuleTask();
priceRuleTask.setId(id); updatePriceRuleTask.setId(id);
priceRuleTask.setCreator(creator); updatePriceRuleTask.setCreator(plainText);
int rows = this.priceRuleTaskMapper.updateByPrimaryKeySelective(priceRuleTask); int rows = this.priceRuleTaskMapper.updateByPrimaryKeySelective(updatePriceRuleTask);
log.debug(">>>>>>>>>>>>{}", rows); log.debug("rows={}", rows);
return String.valueOf(rows); return String.valueOf(rows);
} }
} }
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
useGeneratedKeys="true" keyProperty="id" keyColumn="id"> useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into t_price_rule_task (brand_id,task_id, merge_task_id, task_type, task_status, trigger_type, insert into t_price_rule_task (brand_id,task_id, merge_task_id, task_type, task_status, trigger_type,
check_status, check_point_date,push_status,europe_push_status,remark,cacl_time,shard_no, create_date,creator_id, creator, version) check_status, check_point_date,push_status,europe_push_status,remark,cacl_time,shard_no, create_date,creator_id, creator, version)
values (#{brandId,jdbcType=BIGINT},#{taskId,jdbcType=VARCHAR}, #{merge_task_id,jdbcType=VARCHAR}, #{taskType,jdbcType=TINYINT}, #{taskStatus,jdbcType=INTEGER},#{triggerType,jdbcType=TINYINT}, values (#{brandId,jdbcType=BIGINT},#{taskId,jdbcType=VARCHAR}, #{mergeTaskId,jdbcType=VARCHAR}, #{taskType,jdbcType=TINYINT}, #{taskStatus,jdbcType=INTEGER},#{triggerType,jdbcType=TINYINT},
#{checkStatus,jdbcType=INTEGER}, #{checkPointDate,jdbcType=TIMESTAMP},#{pushStatus,jdbcType=INTEGER},#{europePushStatus,jdbcType=INTEGER},#{remark,jdbcType=VARCHAR},#{caclTime}, #{checkStatus,jdbcType=INTEGER}, #{checkPointDate,jdbcType=TIMESTAMP},#{pushStatus,jdbcType=INTEGER},#{europePushStatus,jdbcType=INTEGER},#{remark,jdbcType=VARCHAR},#{caclTime},
#{shardNo,jdbcType=TINYINT},now(),#{creatorId,jdbcType=BIGINT},#{creator,jdbcType=VARCHAR}, 1) #{shardNo,jdbcType=TINYINT},now(),#{creatorId,jdbcType=BIGINT},#{creator,jdbcType=VARCHAR}, 1)
</insert> </insert>
......
...@@ -3,30 +3,29 @@ spring: ...@@ -3,30 +3,29 @@ spring:
name: price-activity name: price-activity
datasource: datasource:
security: security:
rules: secooActivityDB:
secooActivityDB: t_price_rule_task:
t_price_rule_task: creator:
creator: encryptKey: 123456
encryptKey: 123 encryptType: AES
encryptType: AES plainColumn: creator
plainColumn: creator cipherColumn: creator
cipherColumn: creator modifior:
modifior: encryptKey: 123456
encryptKey: 123 encryptType: AES
encryptType: AES plainColumn: modifior
plainColumn: modifior cipherColumn: modifior
cipherColumn: modifior t_smart_batch:
t_smart_batch: creator:
creator: encryptKey: 123456
encryptKey: 456 encryptType: AES
encryptType: AES plainColumn: creator
plainColumn: creator cipherColumn: creator
cipherColumn: creator modifior:
modifior: encryptKey: 123456
encryptKey: 456 encryptType: AES
encryptType: AES plainColumn: modifior
plainColumn: modifior cipherColumn: modifior
cipherColumn: modifior
server: server:
......
...@@ -73,4 +73,13 @@ public final class AESEncryptAlgorithm implements EncryptAlgorithm { ...@@ -73,4 +73,13 @@ public final class AESEncryptAlgorithm implements EncryptAlgorithm {
result.init(decryptMode, new SecretKeySpec(secretKey, getType())); result.init(decryptMode, new SecretKeySpec(secretKey, getType()));
return result; return result;
} }
public static void main(String[] args) throws GeneralSecurityException {
AESEncryptAlgorithm aesEncryptAlgorithm = new AESEncryptAlgorithm();
aesEncryptAlgorithm.getProps().put(ENCRYPT_KEY,"123456");
aesEncryptAlgorithm.init();
System.out.println(aesEncryptAlgorithm.encrypt("test"));
System.out.println(aesEncryptAlgorithm.decrypt("9b8WmZSaJlkYXZCu8lwxPw=="));
}
} }
package com.secoo.mall.datasource.security.algorithm.encrypt;
import com.secoo.mall.datasource.security.constant.EncryptType;
import org.apache.commons.codec.digest.DigestUtils;
import java.security.GeneralSecurityException;
import java.util.Properties;
/**
* MD5 encrypt algorithm.
*/
public class MD5EncryptAlgorithm implements EncryptAlgorithm {
private Properties props = new Properties();
@Override
public void init() {
}
@Override
public String encrypt(Object plainText) throws GeneralSecurityException {
if (null == plainText) {
return null;
}
return DigestUtils.md5Hex(String.valueOf(plainText));
}
@Override
public String decrypt(String cipherText) throws GeneralSecurityException {
return cipherText;
}
@Override
public String getType() {
return EncryptType.MD5;
}
@Override
public Properties getProps() {
return props;
}
@Override
public void setProps(Properties props) {
this.props = props;
}
}
...@@ -29,13 +29,18 @@ import java.util.stream.Collectors; ...@@ -29,13 +29,18 @@ import java.util.stream.Collectors;
*/ */
public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorithm { public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorithm {
private static Logger log = LoggerFactory.getLogger(ApolloPropertyProviderAlgorithm.class); private static final Logger log = LoggerFactory.getLogger(ApolloPropertyProviderAlgorithm.class);
private static String DATASOURCE_SECURITY_APOLLO_NAMESPACE = "arch.db_config"; private static final String DATASOURCE_SECURITY_APOLLO_NAMESPACE = "arch.db_config";
private Properties props = new Properties(); private Properties props = new Properties();
@Override @Override
public void init() {
}
@Override
public DataSourceSecurityProperties load() { public DataSourceSecurityProperties load() {
log.info("load security config from apollo..."); log.info("load security config from apollo...");
Config appConfig = ConfigService.getConfig(DATASOURCE_SECURITY_APOLLO_NAMESPACE); Config appConfig = ConfigService.getConfig(DATASOURCE_SECURITY_APOLLO_NAMESPACE);
...@@ -87,11 +92,12 @@ public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorith ...@@ -87,11 +92,12 @@ public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorith
} }
Map<String, List<String[]>> columnSectionMap = columnSections.stream().collect(Collectors.groupingBy(columnSection -> columnSection[2])); Map<String, List<String[]>> columnSectionMap = columnSections.stream().collect(Collectors.groupingBy(columnSection -> columnSection[2]));
for(Map.Entry<String,List<String[]>> columnSectionEntry:columnSectionMap.entrySet()){ for(Map.Entry<String,List<String[]>> columnSectionEntry:columnSectionMap.entrySet()){
String columnName = columnSectionEntry.getKey(); String logicColumn = columnSectionEntry.getKey();
if(StringUtils.isBlank(columnName)){ if(StringUtils.isBlank(logicColumn)){
continue; continue;
} }
ColumnRule columnRule = new ColumnRule(); ColumnRule columnRule = new ColumnRule();
columnRule.setLogicColumn(logicColumn);
// field // field
List<String[]> fieldSections = columnSectionEntry.getValue(); List<String[]> fieldSections = columnSectionEntry.getValue();
...@@ -154,8 +160,13 @@ public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorith ...@@ -154,8 +160,13 @@ public class ApolloPropertyProviderAlgorithm implements PropertyProviderAlgorith
} }
@Override @Override
public void init() { public Properties getProps() {
return props;
}
@Override
public void setProps(Properties props) {
this.props = props;
} }
public static void main(String[] args) { public static void main(String[] args) {
......
...@@ -3,4 +3,5 @@ package com.secoo.mall.datasource.security.constant; ...@@ -3,4 +3,5 @@ package com.secoo.mall.datasource.security.constant;
public class EncryptType { public class EncryptType {
public static final String AES = "aes"; public static final String AES = "aes";
public static final String RC4 = "rc4"; public static final String RC4 = "rc4";
public static final String MD5 = "md5";
} }
...@@ -402,7 +402,7 @@ public class SecurityFilter extends FilterEventAdapter { ...@@ -402,7 +402,7 @@ public class SecurityFilter extends FilterEventAdapter {
// 处理set // 处理set
for (SQLUpdateSetItem item : updateStmt.getItems()) { for (SQLUpdateSetItem item : updateStmt.getItems()) {
SQLExpr column = item.getColumn(); SQLExpr column = item.getColumn();
SQLExpr value = item.getColumn(); SQLExpr value = item.getValue();
if (!(value instanceof SQLVariantRefExpr)) { if (!(value instanceof SQLVariantRefExpr)) {
continue; continue;
...@@ -524,7 +524,7 @@ public class SecurityFilter extends FilterEventAdapter { ...@@ -524,7 +524,7 @@ public class SecurityFilter extends FilterEventAdapter {
Map<String, ColumnRule> columnRuleMap = new HashMap<>(); Map<String, ColumnRule> columnRuleMap = new HashMap<>();
for(ColumnRule columnRule:tableRule.getColumnRules()){ for(ColumnRule columnRule:tableRule.getColumnRules()){
columnRuleMap.put(columnRule.getCipherColumn(),columnRule); columnRuleMap.put(columnRule.getLogicColumn(),columnRule);
} }
tableRuleMap.put(tableRule.getTableName(),columnRuleMap); tableRuleMap.put(tableRule.getTableName(),columnRuleMap);
......
...@@ -21,6 +21,11 @@ public class ColumnRule { ...@@ -21,6 +21,11 @@ public class ColumnRule {
private String cipherColumn; private String cipherColumn;
/** /**
* 逻辑字段名称
*/
private String logicColumn;
/**
* 加密器 * 加密器
*/ */
private EncryptAlgorithm encryptAlgorithm; private EncryptAlgorithm encryptAlgorithm;
...@@ -57,6 +62,14 @@ public class ColumnRule { ...@@ -57,6 +62,14 @@ public class ColumnRule {
this.cipherColumn = cipherColumn; this.cipherColumn = cipherColumn;
} }
public String getLogicColumn() {
return logicColumn;
}
public void setLogicColumn(String logicColumn) {
this.logicColumn = logicColumn;
}
public EncryptAlgorithm getEncryptAlgorithm() { public EncryptAlgorithm getEncryptAlgorithm() {
return encryptAlgorithm; return encryptAlgorithm;
} }
...@@ -72,7 +85,7 @@ public class ColumnRule { ...@@ -72,7 +85,7 @@ public class ColumnRule {
", encryptKey='" + encryptKey + '\'' + ", encryptKey='" + encryptKey + '\'' +
", plainColumn='" + plainColumn + '\'' + ", plainColumn='" + plainColumn + '\'' +
", cipherColumn='" + cipherColumn + '\'' + ", cipherColumn='" + cipherColumn + '\'' +
", encryptAlgorithm=" + encryptAlgorithm + ", logicColumn='" + logicColumn + '\'' +
'}'; '}';
} }
} }
...@@ -22,7 +22,7 @@ import java.util.Map; ...@@ -22,7 +22,7 @@ import java.util.Map;
public class SQLParserTest { public class SQLParserTest {
public static void testVisitor(){ public static void testVisitor(){
// String sql = "select u.name,a.age from t_user u,t_account a where u.id = a.id and t_account.id > 12 and a.age >?;"; String sql = "select u.name,a.age from t_user u,t_account a where u.id = a.id and t_account.id > 12 and a.age >? order by id desc;";
// String sql = "select secooStoreDB.t_sequence.`code` from secooStoreDB.t_sequence,secooStoreDB.t_store_fail_mq where secooStoreDB.t_sequence.`code`=secooStoreDB.t_store_fail_mq.topic"; // String sql = "select secooStoreDB.t_sequence.`code` from secooStoreDB.t_sequence,secooStoreDB.t_store_fail_mq where secooStoreDB.t_sequence.`code`=secooStoreDB.t_store_fail_mq.topic";
// String sql = "delete from t_sequence"; // String sql = "delete from t_sequence";
// String sql = "INSERT INTO `secooStoreDB`.`t_sequence`(`t_sequence`.`name`, `current_value`, `increment`, `code`) VALUES (?, 4551, 1, 2),('t_store_category', 65015, 1, 1);"; // String sql = "INSERT INTO `secooStoreDB`.`t_sequence`(`t_sequence`.`name`, `current_value`, `increment`, `code`) VALUES (?, 4551, 1, 2),('t_store_category', 65015, 1, 1);";
...@@ -30,7 +30,7 @@ public class SQLParserTest { ...@@ -30,7 +30,7 @@ public class SQLParserTest {
// String sql = "update t_user set name=?,age=10 where id = id and id > 12"; // String sql = "update t_user set name=?,age=10 where id = id and id > 12";
// String sql = "update t_user u,t_account a set u.name=?,a.age=10 where u.id = a.id and u.id > 12 and a.age >?"; // String sql = "update t_user u,t_account a set u.name=?,a.age=10 where u.id = a.id and u.id > 12 and a.age >?";
// String sql = "update t_user u,t_account a set t_user.name=?,a.age=10 where u.id = a.id and u.id > 12 and a.age >?"; // String sql = "update t_user u,t_account a set t_user.name=?,a.age=10 where u.id = a.id and u.id > 12 and a.age >?";
String sql = "update t_user u,t_account a set secooStoreDB.t_account.name=?,a.age=10 where secooStoreDB.t_account.id = a.id and u.id > 12 and a.age >?"; // String sql = "update t_user u,t_account a set secooStoreDB.t_account.name=?,a.age=10 where secooStoreDB.t_account.id = a.id and u.id > 12 and a.age >?";
// 解析sql // 解析sql
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql,"mysql"); List<SQLStatement> stmtList = SQLUtils.parseStatements(sql,"mysql");
...@@ -42,7 +42,10 @@ public class SQLParserTest { ...@@ -42,7 +42,10 @@ public class SQLParserTest {
if (stmt instanceof SQLSelectStatement) { if (stmt instanceof SQLSelectStatement) {
SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;
System.out.println(visitor.getColumns()); System.out.println(visitor.getColumns());
System.out.println(selectStmt.getSelect()); // System.out.println(selectStmt.getSelect().getQueryBlock().removeCondition("t_account.id > 12"));
System.out.println(selectStmt.toString());
System.out.println(selectStmt.getSelect().getQueryBlock().getSelectList());
System.out.println(selectStmt.getSelect().getQueryBlock().getWhere());
System.out.println("---"); System.out.println("---");
}else if(stmt instanceof MySqlDeleteStatement){ }else if(stmt instanceof MySqlDeleteStatement){
MySqlDeleteStatement deleteStmt = (MySqlDeleteStatement) stmt; MySqlDeleteStatement deleteStmt = (MySqlDeleteStatement) stmt;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment