给hibernate配置文件加密、解密的方案
|
【IT168 技术文档】 |
之前有人问过hibernate密码问题,大家都没有给出一个具体的解决方案,所以我就看了一下代码,把我的想法和实现拿出来和大家讨论一下。我现在的环境是spring+hibernate,但是这并不影响这个加密解密的问题,其他环境应该是略有不同,但是思路肯定是一样的。
总体思路:在工程的配置文件中填写数据库密码的密文,在应用程序使用datasource的时候解密成明文以创建连接。
步骤1
使用java的中cipher类并使用DES(对称加密算法)算法对明文进行加密
````````````````这里如何使用cipher类和DES算法的原理可以上网查找,我懒得写了,如果大家真的也怕麻烦自己去找的话我再写一个贴出来吧
通过以上的encrypt方法得到一个密码的密文(一般的密码是明文,作为参数传进去可以得到对应的密文),比如说21sadf251public class DESUtil ...{ 2
3
public static void main(String[] args)...{ 4
try ...{ 5
if(args[0].equals("-genKey"))...{ 6
generateKey(args[1]); 7
}else...{ 8
9
//if (args[0].equals("-encrypt"))encrypt(); 10
11
//else decrypt(); 12
} 13
}catch (Exception e) ...{ 14
// TODO: handle exception 15
} 16
} 17
18
public static String encrypt(String plainText, String encryptString, File keyFile)throws IOException, ClassNotFoundException,GeneralSecurityException...{ 19
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(keyFile)); 20
int mode = Cipher.ENCRYPT_MODE; 21
Key key = (Key)keyIn.readObject(); 22
keyIn.close(); 23
24
InputStream in = new FileInputStream(plainText); 25
OutputStream out = new FileOutputStream(encryptString); 26
27
Cipher cipher = Cipher.getInstance("DES"); 28
cipher.init(mode, key); 29
30
doEncryptAndDecrypt(in, out, cipher); 31
32
String result = out.toString(); 33
System.out.print(result); 34
in.close(); 35
out.close(); 36
return result; 37
} 38
39
public static String decrypt(String encryptString, String plainText, File keyFile)throws IOException, ClassNotFoundException,GeneralSecurityException...{ 40
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(keyFile)); 41
int mode = Cipher.DECRYPT_MODE; 42
Key key = (Key)keyIn.readObject(); 43
keyIn.close(); 44
45
InputStream in = new FileInputStream(encryptString); 46
OutputStream out = new FileOutputStream(plainText); 47
48
Cipher cipher = Cipher.getInstance("DES"); 49
cipher.init(mode, key); 50
51
doEncryptAndDecrypt(in, out, cipher); 52
53
String result = out.toString(); 54
System.out.print(result); 55
in.close(); 56
out.close(); 57
return result; 58
} 59
60
public static void doEncryptAndDecrypt(InputStream in, OutputStream out, Cipher cipher)throws IOException, GeneralSecurityException...{ 61
int blockSize = cipher.getBlockSize(); 62
int outputSize = cipher.getOutputSize(blockSize); 63
64
byte[] inBytes = new byte[blockSize]; 65
byte[] outBytes = new byte[outputSize]; 66
67
int inLength = 0; 68
boolean more = true; 69
70
while(more)...{ 71
inLength = in.read(inBytes); 72
if(inLength == blockSize)...{ 73
int outLength = cipher.update(inBytes, 0, blockSize, outBytes); 74
out.write(outBytes,0,outLength); 75
} 76
else more = false; 77
} 78
79
if(inLength>0) outBytes = cipher.doFinal(inBytes, 0, inLength); 80
else outBytes = cipher.doFinal(); 81
82
out.write(outBytes); 83
84
} 85
86
public static void generateKey(String path) throws Exception...{ 87
KeyGenerator keygen = KeyGenerator.getInstance("DES"); 88
SecureRandom random = new SecureRandom(); 89
90
keygen.init(random); 91
SecretKey key = keygen.generateKey(); 92
93
ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream(path)); 94
out.writeObject(key); 95
out.close(); 96
} 97
98
} 99
将加密后的密文添加到配置文件中
代码:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=utf-8&autoReconnect=true"/>
<property name="username" value="root"/>
<property name="password" value="21sadf25"/>
<property name="maxActive" value="100"/>
<property name="whenExhaustedAction" value="1"/>
<property name="maxWait" value="120000"/>
<property name="maxIdle" value="30"/>
<property name="defaultAutoCommit" value="true"/>
</bean>
步骤3
继承spring的LocalSessionFactoryBean类,override其setDataSource方法,将dataSource的password取出,解密后再赋值。
为什么要这么做呢,因为datasource是localsessionFactoryBean的一个属性,在注入dataSource时将其密码解密是比较恰当的。所以选择这个setDataSource方法进行override。假设我们使用的dbcp连接池
代码如下:(类名是AhuaXuanLocalSessionFactoryBean)
代码:
配置如下:1public void setDataSource(DataSource dataSource) ...{ 2
String password = (BasicDataSource)dataSource.getPassword(); 3
//通过cipher类进行解密 4
String decryPassword = DESUtil.decrypt(password); 5
dataSource.setPassword(decryPassword); 6
this.dataSource = dataSource; 7
} 8
之前robbin说的DataSourceFactoryBean那个类我在spring1.2.8中没有找到,但是我觉得改造LocalSessionFactoryBean也不错.1<bean id="sessionFactory" class="org.springframework.orm.hibernate.AhuaXuanLocalSessionFactoryBean"> 2
<property name="dataSource"> 3
<ref bean="dataSource"/> 4
</property> 5
</bean> 6
0
相关文章
