老鬼的博客 来都来啦,那就随便看看吧~
java如何连接tomcat加密password字段的JNDI
发布于: 2020-08-05 更新于: 2020-08-05 分类于: Tomcat 阅读次数: 

一:介绍

1
2
3
应客户IT要求,需要对tomcat配置的JNDI中的password进行
解密处理,就是原本JNDI应该配置的明文密码变成密文的密
码,然后还要保证能连接数据库。

二:原理

2.1 明文的context.xml JNDI

1
2
3
4
5
6
7
8
9
10
11
12
13
<Resource 
name="jdbc/chncitosql02-buplanner"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="sa"
password="a123456a"
factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://sit:21433;DatabaseName=businessplanner"
/>

2.2 密文的context.xml JNDI

1
2
3
4
5
6
7
8
9
10
11
12
13
<Resource 
name="jdbc/chncitosql02-buplanner"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="sa"
password="cYQzL68vCszgg9BZ3BC8C6tiTyrM188lMWa8RWy0y0k="
factory="com.tohours.elearning.util.SecurityDataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://sit:21433;DatabaseName=businessplanner"
/>

2.3 如何实现?

1
2
3
仔细的同学不难发现,上面的JNDI有一个factory配置不一样,
其中明文的是用的tomcat的factory,密文是用的自定义的,其实
就是再原本tomcat的factory基础上做调整,进行password的解密操作。

三:定义自己的数据库连接池

3.1 原理

1
在基于tomcat-dbcp.jar连接池的基础上做改造,重写BasicDataSourceFactory的一个方法。

3.2 步骤

1
2
3
4
项目引入tomcat-dbcp.jar,此文件在tomcat/lib下可以找到,也可以在下面地址下载,
我默认拿的是tomcat9的jar包,不同版本有区别,包名不一致,tomcat7和7之前用的是
org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory,tomcat7以后用的是
org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory

tomcat9的tomcat-dbcp.jar包下载

3.3 定义自己的SecurityDataSourceFactory类

1
2
3
4
我这里的全路径是com.tohours.elearning.util.SecurityDataSourceFactory,
所以密文的tomcat JNDI配置的是这个路径,其中SecurityDataSourceFactory
中引入了DBAesUtils.java,这个就是用的aes加解密,这里可以提换成自己用
的加解密的方法。
  • SecurityDataSourceFactory.java
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
package com.tohours.elearning.util;

import javax.naming.RefAddr;
import javax.naming.Reference;

import org.apache.log4j.Logger;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory;

public class SecurityDataSourceFactory extends BasicDataSourceFactory {

private Logger log = Logger.getLogger(SecurityDataSourceFactory.class);

@Override
@SuppressWarnings("rawtypes")
public Object getObjectInstance(Object obj, javax.naming.Name name, javax.naming.Context nameCtx,
java.util.Hashtable environment) throws Exception {

if ((obj == null) || !(obj instanceof Reference)) {
return null;
}

Reference ref = (Reference) obj;

RefAddr ra = null;
int len = ref.size();
for (int i = 0; i < len; i++) {
ra = ref.get(i);
log.info("type" + (i+1) + ":" + ra.getType());
if ("password".equalsIgnoreCase(ra.getType())) {
ref.remove(i);
ref.add(i, new TransformRefAddr(ra) {
private static final long serialVersionUID = 1L;
@Override
public Object transform(Object obj) {
return DBAesUtils.decrypt(obj.toString());
}
});
}
}

return super.getObjectInstance(obj, name, nameCtx, environment);
};

private abstract class TransformRefAddr extends RefAddr {
private static final long serialVersionUID = 1L;

private RefAddr refAddr;

public TransformRefAddr(RefAddr refAddr) {
super(refAddr.getType());
this.refAddr = refAddr;
}
@Override
public Object getContent() {

return this.transform(refAddr.getContent());
}

public abstract Object transform(Object obj);

}
}

*************感谢您的阅读*************