该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-13
之前有人问过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也不错 这样就完成了一个我们的目标,以上代码是随便写的,没有经过测试,有兴趣的同学可以试一下 作者:张荣华,未经作者同意不得随意转载! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-04-13
lixuehui 写道 没觉得安全性高在哪,真实密码照样在程序中出现.
很容易就被破解了,照样可以得到数据库的真实密码 不可取 你发布工程的时候不能混淆一下吗,我还没有见不在代码中读取密码的安全应用呢 |
|
返回顶楼 | |
发表时间:2007-04-13
我在想一个问题,能不能想办法对setPassword方法进行拦截器拦截,这样一来任何需要加密的地方都拦截一下就可以了.
|
|
返回顶楼 | |
发表时间:2007-04-16
我还记得四年前我想通过一些非常手法来获取数据库的口令,却被一个同事批评了一通,他说,既然是bs模式,就没有必要在服务器上去加密数据库口令了;因为如果有人能进入服务器了,你还能阻止他什么?
当然日常的安全性我们还是需要考虑的。 |
|
返回顶楼 | |
发表时间:2007-04-17
可以参考一下.net配置文件的加密方式,把加密解密委托给别的程序。
|
|
返回顶楼 | |
发表时间:2007-04-17
用jndi是最安全的,其它方式都可能有问题,即使是通过混淆代码,一样是有办法解开的
|
|
返回顶楼 | |
发表时间:2007-04-23
小开ye 写道 我还记得四年前我想通过一些非常手法来获取数据库的口令,却被一个同事批评了一通,他说,既然是bs模式,就没有必要在服务器上去加密数据库口令了;因为如果有人能进入服务器了,你还能阻止他什么?
能入侵服务器的黑客就一定能知道服务器上数据的密码吗,他可以在应用程序的配置文件中找数据库密码,如果应用程序的数据库password被保护了,至少在一定程度上阻止了他的步伐,如果他水平很高,对加密解密很了解,说不定能破解(或者用其他什么工具直接破解数据库密码,我猜的),但前提的他是黑客中的高手,但是事实告诉我们黑客中的菜鸟也不少,只会用点小工具去扫描扫描端口等等,不同的客户不同的应用是需要不同的安全级别的
|
|
返回顶楼 | |
发表时间:2007-05-29
这样也足够用了,加密过的密码放在配置文件中,就算看得到有什么关系呢?
这里讨论的也不是加密的方案如何如何安全可靠,重点还是能够在创建datasource的时候得到正确的密码明文, 黑客入侵就扯得远了嘛. |
|
返回顶楼 | |
发表时间:2007-05-29
加密的作用就是让黑客一次破解的周期延长。。。。并提高发现可能
而不是为了让他破不开。。。 至少要大于24小时。。。 那样的话。。。不用24小时守着电脑了。 |
|
返回顶楼 | |
发表时间:2007-06-04
没必要吧,人家要是连你的配置文件都看了.还有什么干不了呢.安全问题应该从服务器整体考虑.
|
|
返回顶楼 | |