Hibernate配置文件hibernate.cfg.xml中存放了我们连接数据库的相关信息,其中设计到许多数据库的敏感信息,比如连接地址,用户名和密码,有时候我们交由发布组进行发布时并不希望他们看到数据库的连接密码,就需要对hibernate配置文件中的部分信息进行加密,我在解决这一问题中实践了三种方法,第一种是重载连接供应器,第二种是使用Hibernate官方推荐的Jasypt,第三种其实算不上是加密,而是使用WebLogic连接池将相关信息放在WebLogic的配置中,下面会具体阐述这三种方法。
第一种重载连接供应器:
这种方法是我在网上看到的,原文连接是:
http://blog.csdn.net/sdbany/archive/2008/10/23/3132809.aspx
但是在实际使用的时候发现代码有问题,可能是作者没有贴全,所以有些功能无法实现,于是我重新写了代码。
首先创建一个连接供应器,配置文件里的参数解释都是此类负责,所以,只要在此类中进行密文解密即可。
Java代码
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment;
import org.hibernate.connection.DriverManagerConnectionProvider;
public class CustomDriverManagerConnectionProvider extends
DriverManagerConnectionProvider {
public CustomDriverManagerConnectionProvider() {
super();
}
@Override
public void configure(Properties props) throws HibernateException{
String user = props.getProperty(Environment.USER);
String password = props.getProperty(Environment.PASS);
props.setProperty(Environment.USER, SecUtil.decrypt(user));
props.setProperty(Environment.PASS, SecUtil.decrypt(password));
super.configure(props);
}
}
再写一个类,使用AES负责字符串的加密与解密这里我们参照原作者的方法
Java代码
/**
* AES加密工具
*
* @author Bany
*
* @version 创建时间:2008-8-5 上午10:58:16
*
*/
public class SecUtil {
private static byte[] keybytes = { 0x31, 0x32, …… };
public static void main(String[] args) throws Exception {
String e1 = encrypt("newpassword");
System.out.println(e1);
String e2 = decrypt(e1);
System.out.println(e2);
}
/**
* 加密
* @param value
* @return
*/
public static String encrypt(String value) {
String s=null;
int mode = Cipher.ENCRYPT_MODE;
try {
Cipher cipher = initCipher(mode);
byte[] outBytes = cipher.doFinal(value.getBytes());
s = String.valueOf(Hex.encodeHex(outBytes));
} catch (Exception e) {
e.printStackTrace();
}
return s;
}
/**
* 解密
* @param value
* @return
*/
public static String decrypt(String value) {
String s = null;
int mode = Cipher.DECRYPT_MODE;
try {
Cipher cipher = initCipher(mode);
byte[] outBytes = cipher.doFinal(Hex.decodeHex(value.toCharArray()));
s = new String(outBytes);
} catch (Exception e) {
e.printStackTrace();
}
return s;
}
private static Cipher initCipher(int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
Key key = new SecretKeySpec(keybytes, "AES");
cipher.init(mode, key);
return cipher;
}
}
当然,你也可以使用自己写的加密方法,或者是Java官方推荐的一些加密方法
调用SecUtil.encrypt的方法,把用户密码加密生成密文,然后根据密文修改hibernate.cfg.xml文件
Xml代码
<property name="connection.username">c59cd98</property>
<property name="connection.password">68e32593ea5943a6a</property>
<property name="connection.provider_class">com.CustomDriverManagerConnectionProvider</property>
第一二行是加密后的密文,第三行是使用自定义的连接器
如果使用第三方的连接器,CustomDriverManagerConnectionProvider则需要继承于相应的连接器,如C3P0ConnectionProvider
第二种:使用Hibernate官方推荐的Jasypt
首先来了解什么是Jasypt
引用
Jasypt这个Java类包为开发人员提供一种简单的方式来为项目增加加密功能,包括:密码Digest认证,文本和对象加密,集成hibernate,Spring Security(Acegi)来增强密码管理。
你可以从SourceForge.net下载最新的Jasypt(目前的最新版本是1.5)
另外,使用Jasypt还需要几个Jar包的支持,分别是:
commons-codec-1.1.jar 和 commons-lang-2.1.jar这在你下载Jasypt压缩包的lib目录里已经附带了,如果你是Java SE 5或更早的版本,就需要ICU3.4.4或更高版本的支持,这些文件都可以在Jasypt网站的Dependencies项下找到。
另外,我们要了解一下Jasypt的加密方式,Jasypt提供了多种的加密方式,更允许用户自己编写加密方法,或使用Java增强加密算法(譬如 TripleDES)也可添加相应的包来扩展。
这里只介绍Jasypt默认的加密方法,其他方法感兴趣的朋友可以自己去研究;
Jasypt默认使用了对称加密的方法,即加密密钥和解密密钥是相同的,流程如下
引用
明文(可以是要加密的密码) + 密钥 =Jasypt默认算法=> 密文
解密过程与之相反
为了得到密文,我们先要使用Jasypt自带的工具,在下载Jasypt压缩包的bin目录中有如下文件:
引用
decrypt.bat
decrypt.sh
digest.bat
digest.sh
encrypt.bat
encrypt.sh
jasypt-cli-bundle.jar
README_IMPORTANT.txt
我们要用到encrypt命令来实现上面的过程加密明文,命令如下:
Console代码
encrypt input=明文(可以是密码) password=密钥
上面的明文和密钥都不要加引号,output就是需要的密文,将其记录下来
得到密文以后,工作就很简单了
首先在你的项目中添加需要的包(jasypt-1.5.jar, commons-codec-1.1.jar, commons-lang-2.1.jar, icu4j-4_0.zip)
之后修改hibernate.cfg.xml文件
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.provider_class">
org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider
</property> <!-- 这个是添加的provider类 -->
<property name="connection.encryptor_registered_name">
configurationHibernateEncryptor
</property> <!-- 这里是加密密钥 -->
<property name="connection.url">jdbc:mysql://localhost/reportsdb</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">reportsUser</property>
<property name="connection.password">ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)</property><!-- 这里的格式是ENC(密文) -->
<property name="connection.pool_size">12</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Mappings etc... -->
</session-factory>
</hibernate-configuration>
上面标注的地方是必须的,其他可以按照自己的实际配置,重新编译项目,就完成了。
另:第一种重载连接供应器
前面说了两种保护Hibernate配置文件中密码不被泄露的方法,今天接着介绍第三种,之前已经说过,其实这算不上加密方法,但是可以说是三种方法中安全性最高的,就是使用WebLogic自动的连接池来实现数据库的连接,而我们只需要在Hibernate文件中进行简单的配置就可以连接到数据库,具体的步骤如下:
WebLogic JNDI连接池的配置
1. console登陆,点击左边AdminServerName -> Services -> JDBC -> DataSources
2. 点击左上角的Lock & Edit
3. 点击DataSources中的New按钮
4. Name输入连接的名字(可以随便起,建议用数据库的名字命名便于区分),JNDI Name是JNDI连接的名字(在后面的配置文件中要用到),数据库类型选择Oracle(如果你是其他类型的数据库也可以选其他的),数据库Driver如图选择*Oracle’s Driver (Thin) Versions:9.0.1.9.2.0.10(这种Driver的速度快),点击Next进入下一步。
5. 这里使用默认设置即可,点击Next进入下一步。
6. 这个页面是设置数据库连接的详细信息,DatabaseName需要连接的数据库名称,HostName输入数据库的IP或者主机名,Port是连接端口,使用默认的1521,之后输入连接的用户名和密码,并输入确认密码,点击Next进入下一步。
7. 这个页面是让你确认之前填写的设置,还可以点击Test Configuration测试连接是否成功,如果成功,会出现Connection test succeeded.的提示,点击Next进入下一步。
8. 勾选AdminServer连接池自动启动,点击Finish完成设置。
之后在Hibernate配置文件中需要进行相关的设置:
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">SurveyJNDI</property>
<!-- 这个是前面填写的JNDI Name -->
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Mappings etc... -->
</session-factory>
</hibernate-configuration>
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">SurveyJNDI</property>
<!-- 这个是前面填写的JNDI Name -->
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Mappings etc... -->
</session-factory>
</hibernate-configuration>
上面标注的地方是必须的,其他的用户名,密码连接url都不需要了。
将项目发布到WebLogic服务器上就可使用WebLogic提供的连接池来连接数据库了。