使用Tomcat jndi安全连接数据库
需求概要
公司因被恶意攻击, 上级传达要求, 所有的敏感数据必须加密, 所有项目开发必须脱离数据库账号密码, 于是就有了变更数据库连接方式, 采用jndi.
运维负责在Tomcat conf下配置jdbc, 并提供一个数据源名称, 开发通过数据源名称连接数据库, 开发不沾手数据库账号密码, 保证安全由运维统一控制
代码修改
1. 原始代码(spring datasource原始配置)
- 1.1 spring-datasource.xml
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="name" value="CBoard Meta Data"/>
<property name="url" value="${jdbc_url}"/>
<property name="username" value="${jdbc_username}"/>
<property name="password" value="${jdbc_password}"/>
<property name="initialSize" value="0"/>
<property name="maxActive" value="20"/>
<property name="minIdle" value="0"/>
<property name="maxWait" value="60000"/>
<property name="validationQuery" value="${validationQuery}"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="25200000"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="1800"/>
<property name="logAbandoned" value="true"/>
<property name="filters" value="mergeStat,log4j"/>
</bean>
- 1.2 config.properties
validationQuery=$[validationQuery]
jdbc_url=$[jdbc_url]
jdbc_username=$[jdbc_username]
jdbc_password=$[jdbc_password]
- 1.3 vars.sit.properties
validationQuery=SELECT 1
jdbc_url=jdbc:mysql://172.16.41.156:3306/ocean?characterEncoding=utf-8
jdbc_username=ocean
jdbc_password=ocean
- 1.4 pom.xml
...
<profile>
<id>sit</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>./vars/vars.sit.properties</filter>
</filters>
</build>
</profile>
...
- 1.5 maven打包命令
mvn clean package -Dmaven.skip.test=true -Psit
2. 修改后
- 2.1
spring-datasource.xml
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/${jndi.jndi-name}"/>
</bean>
- 2.2
config.properties
jndi.jndi-name=$[jndi.jndi-name]
- 2.3
vars.sit.properties
jndi.jndi-name=jdbc/oceanBD
- 2.4 pom.xml 同1.4不变
- 2.5
Tomcat lib目录下
添加jar
druid-1.1.12.jar
mysql-connector-java-5.1.24.jar
log4j-1.2.17.jar
- 2.6 修改
Tomcat conf/context.xml
<context>标签下添加<Resource> 标签
如果图方便,jdbc/cboardBD
可以直接在2.1中写死
<Resource name="jdbc/oceanBD"
factory="com.alibaba.druid.pool.DruidDataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://172.16.41.156:3306/ocean?useUnicode=true&characterEncoding=utf-8"
username="ocean"
password="ocean"
initialSize="0"
maxActive="20"
minIdle="0"
maxWait="60000"
validationQuery="select 1"
testOnBorrow="false"
testOnReturn="false"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="60000"
minEvictableIdleTimeMillis="25200000"
removeabandoned="true"
removeabandonedtimeout="1800"
logabandoned="true"
filters="mergeStat,log4j"
connectionProperties="druid.stat.mergeSql=true;druid.stat.slowSqlMillis=2000"
useGlobalDataSourceStat="true"
poolPreparedStatements="false"
maxOpenPreparedStatements="20"
asyncInit="true"/>
- 2.7 maven打包 同1.5
BUG修复
bug概述
- 改完后在idea本地开发环境正常启动并访问,
- 测试环境正常启动且只能访问Tomcat manager项目(Tomcat 自带docs examples host-manager manager ROOT几个内置项目)
开发的项目不能访问
bug排查
- 查看启动日志, 日志无任务报错, 且启动了wepapps下开发的项目和Tomcat自带的项目
- 查看本地和测试环境Tomcat版本, 本地8.0 , 测试8.5, 变更本地为8.5, 本地依旧启动成功
bug解决
- 方案一 删除无关项目
删除webapps下的所有项目, 只保留开发的项目 - 方案二 修改Tomcat conf/server.xml文件
在\<Host \>标签中添加子标签:
<Context path="" docBase="要运行的项目名称" debug="0" reloadable="true"/>
bug解决补充
context.xml 里配置的jndi 改到 server.xml里, 并在context.xml 配置引用, 无法解决上述bug
, 这个可以做全局DataSource与单个项目的DataSource的配置参考, 配置如下
- 将context.xml的 <Resource> 配置到server.xml的<GlobalNamingResources>
- context.xml里配置
bug猜想
启动过程中, Tomcat自带项目覆盖了开发的项目
参考网址
https://www.cnblogs.com/zyxiaohuihui/p/9300282.html (私有数据源/全局配置)
https://www.cnblogs.com/xuange306/p/6398926.html (bug解决方法二操作)
https://blog.csdn.net/deniro_li/article/details/96716817(jndi druid连接参考)