引用:http://www.iteye.com/topic/70663 (先转过来,有需要的时候参考)
如何给工程中的配置文件加密 解密
之前有人问过hibernate密码问题,大家都没有给出一个具体的解决方案,所以我就看了一下代码,把我的想法和实现拿出来和大家讨论一下。
我现在的环境是spring+hibernate,但是这并不影响这个加密解密的问题,其他环境应该是略有不同,但是思路肯定是一样的。
总体思路:在工程的配置文件中填写数据库密码的密文,在应用程序使用datasource的时候解密成明文以创建连接。
步骤1
使用java的中cipher类并使用DES(对称加密算法)算法对明文进行加密
````````````````这里如何使用cipher类和DES算法的原理可以上网查找,我懒得写了,如果大家真的也怕麻烦自己去找的话我再写一个贴出来吧
修改:我随便写了一个类,大家看着改吧,我没有测试过
public class DESUtil { public static void main(String[] args){ try { if(args[0].equals("-genKey")){ generateKey(args[1]); }else{ //if (args[0].equals("-encrypt"))encrypt(); //else decrypt(); } }catch (Exception e) { // TODO: handle exception } } public static String encrypt(String plainText, String encryptString, File keyFile)throws IOException, ClassNotFoundException,GeneralSecurityException{ ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(keyFile)); int mode = Cipher.ENCRYPT_MODE; Key key = (Key)keyIn.readObject(); keyIn.close(); InputStream in = new FileInputStream(plainText); OutputStream out = new FileOutputStream(encryptString); Cipher cipher = Cipher.getInstance("DES"); cipher.init(mode, key); doEncryptAndDecrypt(in, out, cipher); String result = out.toString(); System.out.print(result); in.close(); out.close(); return result; } public static String decrypt(String encryptString, String plainText, File keyFile)throws IOException, ClassNotFoundException,GeneralSecurityException{ ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(keyFile)); int mode = Cipher.DECRYPT_MODE; Key key = (Key)keyIn.readObject(); keyIn.close(); InputStream in = new FileInputStream(encryptString); OutputStream out = new FileOutputStream(plainText); Cipher cipher = Cipher.getInstance("DES"); cipher.init(mode, key); doEncryptAndDecrypt(in, out, cipher); String result = out.toString(); System.out.print(result); in.close(); out.close(); return result; } public static void doEncryptAndDecrypt(InputStream in, OutputStream out, Cipher cipher)throws IOException, GeneralSecurityException{ int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(blockSize); byte[] inBytes = new byte[blockSize]; byte[] outBytes = new byte[outputSize]; int inLength = 0; boolean more = true; while(more){ inLength = in.read(inBytes); if(inLength == blockSize){ int outLength = cipher.update(inBytes, 0, blockSize, outBytes); out.write(outBytes,0,outLength); } else more = false; } if(inLength>0) outBytes = cipher.doFinal(inBytes, 0, inLength); else outBytes = cipher.doFinal(); out.write(outBytes); } public static void generateKey(String path) throws Exception{ KeyGenerator keygen = KeyGenerator.getInstance("DES"); SecureRandom random = new SecureRandom(); keygen.init(random); SecretKey key = keygen.generateKey(); ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream(path)); out.writeObject(key); out.close(); } }
通过以上的encrypt方法得到一个密码的密文(一般的密码是明文,作为参数传进去可以得到对应的密文),比如说21sadf25
步骤2
将加密后的密文添加到配置文件中
<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)
public void setDataSource(DataSource dataSource) { String password = (BasicDataSource)dataSource.getPassword(); //通过cipher类进行解密 String decryPassword = DESUtil.decrypt(password); dataSource.setPassword(decryPassword); this.dataSource = dataSource; }
配置如下:
<bean id="sessionFactory" class="org.springframework.orm.hibernate.AhuaXuanLocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean>
之前robbin说的DataSourceFactoryBean那个类我在spring1.2.8中没有找到,但是我觉得改造LocalSessionFactoryBean也不错
这样就完成了一个我们的目标,以上代码是随便写的,没有经过测试,有兴趣的同学可以试一下
纯转载收藏,有机会在深入,目前还没有在此基础上实现过!!!