一:介绍 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); 	} }