发布于 

数据库密码加解密中间件

项目地址

把项目install 取得jar,执行以下代码手动安装jar

1
mvn install:install-file -Dfile=/Users/edy/Documents/middleware-commons-1.0.4.jar -DgroupId=com.yujian.middleware -DartifactId=middleware-commons -Dversion=1.0.4 -Dpackaging=jar -DgeneratePom=true

参数解释
mvn install:install-file —— 执行 Maven 的 install-file 目标,用于将 JAR 文件手动安装到本地 Maven 仓库。
-Dfile=/Users/edy/Documents/middleware-config-1.0.2(1).jar
指定 JAR 文件的路径(此处 middleware-config-1.0.2(1).jar 似乎是浏览器下载后自动加了 (1) 的文件名,建议去掉括号以免报错)。
-DgroupId=com.yujian.middleware
指定 groupId(通常是 JAR 依赖所属的组织或公司)。
-DartifactId=middleware-config
指定 artifactId(通常是项目名称)。
-Dversion=1.0.2
指定版本号(这里是 1.0.2)。
-Dpackaging=jar
指定打包类型(这里是 jar)。
-DgeneratePom=true
生成 POM 文件(如果该 JAR 没有 POM 文件,Maven 会自动生成)

项目MybatisConfig配置文件改造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package com.touchsmail.common.conf;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.touchsmail.common.dataSources.DataSourceType;
import com.touchsmail.common.dataSources.DynamicDataSource;
import com.yujian.middleware.commons.support.YjDBPasswordFactory;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;

/**
* Mybatis多数据源配置
* 参考文章:https://www.cnblogs.com/geekdc/p/10963476.html
* @ClassName: MybatisConfig
* @author fuce
* @date 2019-12-06 21:11
*/
@Configuration
@MapperScan(basePackages = {"com.touchsmail.mapper","com.touchsmail.website.mapper","com.touchsmail.manager.mapper"})
public class MybatisConfig {

private static final Logger logger = LoggerFactory.getLogger(MybatisConfig.class);

@Bean
@ConfigurationProperties("spring.datasource.druid.master")
public DruidDataSource masterDataSource()
{
return DruidDataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties("spring.datasource.druid.slave")
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
public DataSource slaveDataSource()
{
return DruidDataSourceBuilder.create().build();
}

@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) throws Exception {
Map<Object, Object> targetDataSources = new HashMap<>();
DruidDataSource source = (DruidDataSource) masterDataSource;
YjDBPasswordFactory passwordFactory = new YjDBPasswordFactory();
passwordFactory.setPassword(source.getPassword());
source.setPassword(passwordFactory.getObject());
targetDataSources.put(DataSourceType.MASTER.name(), source);
targetDataSources.put(DataSourceType.SLAVE.name(),slaveDataSource);
return new DynamicDataSource(masterDataSource(), targetDataSources);
}

@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
//核心就是这个,替换原始的SqlSessionFactoryBean 用mybatisSqlSessionFactoryBean即可
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(dynamicDataSource);
// 设置mapper.xml的位置路径


factoryBean.setMapperLocations(resolveMapperLocations());
return factoryBean.getObject();
}

public Resource[] resolveMapperLocations() {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<String> mapperLocations = new ArrayList<>();

mapperLocations.add("classpath*:mybatis/*/*/*.xml");
mapperLocations.add("classpath*:mybatis-plus/*.xml");

List<Resource> resources = new ArrayList<Resource>();
if (mapperLocations != null) {
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
e.printStackTrace();
}
}
}
return resources.toArray(new Resource[resources.size()]);
}



/**
* 配置@Transactional注解事务
* @param dynamicDataSource
* @return
* @author fuce
* @Date 2019年12月7日 上午11:31:33
*/
@Bean
public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource){
return new DataSourceTransactionManager(dynamicDataSource);
}
}

重点在这里

1
2
3
4
5
6
7
8
9
10
11
  public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) throws Exception {
Map<Object, Object> targetDataSources = new HashMap<>();
DruidDataSource source = (DruidDataSource) masterDataSource;
YjDBPasswordFactory passwordFactory = new YjDBPasswordFactory();
passwordFactory.setPassword(source.getPassword());
String dePass = passwordFactory.getObject();
source.setPassword(dePass);
targetDataSources.put(DataSourceType.MASTER.name(), source);
targetDataSources.put(DataSourceType.SLAVE.name(),slaveDataSource);
return new DynamicDataSource(masterDataSource(), targetDataSources);
}

项目中的EncryptDBPasswordFactory文件,用于数据库密码加密、解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.touchsmail.util;

import org.springframework.beans.factory.FactoryBean;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
* 用于数据库密码加密、解密,跟jboss4.0.5兼容 加解密代码源自于org.jboss.resource.security.SecureIdentityLoginModule
*
* @author cy
*/
public class EncryptDBPasswordFactory implements FactoryBean<String> {

/**
* 加密密码
*/
private String password;

/**
* 加密
*
* @param secret
* @return
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
private String encode(String secret, String privateKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
byte[] kbytes = privateKey.getBytes();
SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");

Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encoding = cipher.doFinal(secret.getBytes());
BigInteger n = new BigInteger(encoding);
return n.toString(16);
}

/**
* 解密
*
* @param secret
* @return
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
private char[] decode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
byte[] kbytes = "这里是盐".getBytes();
SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");

BigInteger n = new BigInteger(secret, 16);
byte[] encoding = n.toByteArray();

Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decode = cipher.doFinal(encoding);
return new String(decode).toCharArray();
}

@Override
public String getObject() throws Exception {
if (password != null) {
return String.valueOf(decode(password));
} else {
return null;
}
}

@Override
public Class<String> getObjectType() {
return String.class;
}

@Override
public boolean isSingleton() {
return true;
}

/**
* @param password
*/
public void setPassword(String password) {
this.password = password;
}

public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
BadPaddingException, IllegalBlockSizeException {

EncryptDBPasswordFactory encrypt = new EncryptDBPasswordFactory();

String secret = "";
String secText = encrypt.encode(secret, "");
System.out.println(secText);

System.out.println(encrypt.decode(secText));
}

public static String decodeA(String secret) throws InvalidKeyException, NoSuchPaddingException,
NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {
EncryptDBPasswordFactory encrypt = new EncryptDBPasswordFactory();
return new String(encrypt.decode(secret));
}

}

环境密钥路径:/root/private/dbsecretkey