如何实现数据库连接的密码加密

 

本文转载自:http://zrpingfan.blog.sohu.com/113136684.html

 

 项目需求 :

所有认证数据,例如密码,不论是在储存、传输中都必须妥善保护,以防泄露或被未获授权修改。在安全认证中的Fortify 静态代码分析器的扫描中,如果密码明文放在文件中是肯定过不去的。

 


需求解决方案:
下面具体结合SSH的框架的代码实现。
1. 认证数据加密
所有认证数据通过 3DES 加密;加解密方法如下:

Java代码 1.import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class DesEncrypt {
 /**
  *
  * 使用DES加密与解密,可对byte[],String类型进行加密与解密 密文可使用String,byte[]存储.
  *
  * 方法: void getKey(String strKey)从strKey的字条生成一个Key
  *
  * String getEncString(String strMing)对strMing进行加密,返回String密文 String
  * getDesString(String strMi)对strMin进行解密,返回String明文
  *
  *byte[] getEncCode(byte[] byteS)byte[]型的加密 byte[] getDesCode(byte[]
  * byteD)byte[]型的解密
  */

 Key key;

 /**
  * 根据参数生成KEY
  *
  * @param strKey
  */
 public void getKey(String strKey) {
  try {
   KeyGenerator _generator = KeyGenerator.getInstance("DES");
   _generator.init(new SecureRandom(strKey.getBytes()));
   this.key = _generator.generateKey();
   _generator = null;
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 /**
  * 加密String明文输入,String密文输出
  *
  * @param strMing
  * @return
  */
 public String getEncString(String strMing) {

  byte[] byteMi = null;
  byte[] byteMing = null;
  String strMi = "";
  BASE64Encoder base64en = new BASE64Encoder();
  try {
   byteMing = strMing.getBytes("UTF8");
   byteMi = this.getEncCode(byteMing);
   strMi = base64en.encode(byteMi);
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   base64en = null;
   byteMing = null;
   byteMi = null;
  }
  return strMi;
 }

 /**
  * 解密 以String密文输入,String明文输出
  *
  * @param strMi
  * @return
  */
 public String getDesString(String strMi) {
  BASE64Decoder base64De = new BASE64Decoder();
  byte[] byteMing = null;
  byte[] byteMi = null;
  String strMing = "";
  try {
   byteMi = base64De.decodeBuffer(strMi);
   byteMing = this.getDesCode(byteMi);
   strMing = new String(byteMing, "UTF8");
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   base64De = null;
   byteMing = null;
   byteMi = null;
  }
  return strMing;
 }

 /**
  * 加密以byte[]明文输入,byte[]密文输出
  *
  * @param byteS
  * @return
  */
 private byte[] getEncCode(byte[] byteS) {
  byte[] byteFina = null;
  Cipher cipher;
  try {
   cipher = Cipher.getInstance("DES");
   cipher.init(Cipher.ENCRYPT_MODE, key);
   byteFina = cipher.doFinal(byteS);
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   cipher = null;
  }
  return byteFina;
 }

 /**
  * 解密以byte[]密文输入,以byte[]明文输出
  *
  * @param byteD
  * @return
  */
 private byte[] getDesCode(byte[] byteD) {
  Cipher cipher;
  byte[] byteFina = null;
  try {
   cipher = Cipher.getInstance("DES");
   cipher.init(Cipher.DECRYPT_MODE, key);
   byteFina = cipher.doFinal(byteD);
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   cipher = null;
  }
  return byteFina;
 }

 public static void main(String[] args) {
  System.out.println("des demo");
  DesEncrypt des = new DesEncrypt();// 实例化一个对像
  des.getKey("MYKEY");// 生成密匙
  System.out.println("key=MYKEY");
  String strEnc = des.getEncString("111111");// 加密字符串,返回String的密文
  System.out.println("密文=" + strEnc);
  String strDes = des.getDesString(strEnc);// 把String 类型的密文解密
  System.out.println("明文=" + strDes);
 }
}

 

2. hibernate 数据库连接密码处理
将Hibernate 的数据库连接密码加密放在配置文件和数据库中,具体spring+hibernate 连接配置修改连接如下:

步骤1: 将spring 关于数据源的连接修改如下:

 

Java代码 1.  
2. 
3.          
4. 
5.            oracle.jdbc.driver.OracleDriver  
6. 
7.       
  
8. 
9.          
10. 
11.            jdbc:oracle:thin:@dbServer:1521:feelview  
12. 
13.       
  
14. 
15.          
16. 
17.            feelview  
18. 
19.       
  
20. 
21.          
22. 
23.            %QX7N顴服筜吩d/?  
24. 
25.       
  
26. 
27.   
 

       

            oracle.jdbc.driver.OracleDriver

       

       

            jdbc:oracle:thin:@dbServer:1521:feelview

       

       

            feelview

       

       

            ${jdbc.password}value>

       

     

 

解析:

dataSource 的 class 由 org.apache.commons.dbcp.BasicDataSource 改为自己创建的 com.hqlTest.MyBasicDataSource ;

BasicDataSource 类所做的事只有二件:1,继承 BasicDataSource ;2 ,重写 (override) 密码设置方法 setPassword ;函数 setPassword 中实现密码的 3DES 解密;

MyBasicDataSource代码:

 

import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;

public class MyBasicDataSource extends BasicDataSource {

 

 @Override
 public synchronized void setPassword(String password) {
  //读取jdbc.Properties配置文件中加密后的密码
  PropertiesUtils pro=new PropertiesUtils();
  pro.getFile("jdbc.properties");
  String passwordEncString=pro.read("jdbc.password");
  pro.close();
  System.out.println("password-->"+passwordEncString);
  //将密码解密
  DesEncrypt des=new DesEncrypt();
  des.getKey("MYKEY");//生成密匙
  password= des.getDesString(passwordEncString);// 把String 类型的密文解密
  System.out.println("明文=" + password);
  super.setPassword(password);
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  MyBasicDataSource mbds=new MyBasicDataSource();
  System.out.println(mbds.getPassword());
 }

}

3.PropertiesUtils:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

 

 

public class PropertiesUtils {
 /**
  * ???? 2006 2006-8-18 ????01:40:49
  * 得到文件的输入流
  **/
 private static Properties file = new Properties(); 
 public void getFile(String fileName){
//  Resource resource=new ClassPathResource(fileName);
  InputStream inputStream = getClass().getResourceAsStream("/"+fileName);
  if(inputStream==null){
   System.out.println(fileName+" is  exist!");
  }
  else{
   try {
    file.load(inputStream);
    inputStream.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }
 /**
  * @param propertyName  读取 和写入
  * @return  key
  */
 public String read(String propertyName){
  return  file.getProperty(propertyName);
 }
 public void write(String name,String value){
  file.setProperty(name, value);
 }
 
 /**
  * 关闭文件
  */
 public void close(){
  try {
   OutputStream os=new FileOutputStream("jdbc.properties");
   file.store(os,null);
   /*OutputStream os=new FileOutputStream("src/jdbc.xml");
   prop.storeToXML(os,null);*/
   os.close();
  }catch (Exception e) {
   System.out.println("jdbc.properties无法正常关闭");
  }
 }
 /**
  * 测试
  */
 public static void main(String[] args){
  PropertiesUtils util = new PropertiesUtils();
  util.getFile("jdbc.properties");
  util.write("jdbc.port","10080");
  util.write("jdbc.username","9999");
  util.close();
  String value=util.read("jdbc.url");
  System.out.println("value-->"+value);
 }
}


jdbc.Properties :

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=Ey4pNYUPLxE=


 

==========================================

住:如果是在linux系统下面,会出现登录不上的异常,

修改DesEncrypt.java类中的getkey方法:

    /**
      * 根据参数生成KEY
      *
      * @param strKey
      */
     public void getKey(String strKey) {
      try {
       KeyGenerator _generator = KeyGenerator.getInstance("DES");
//       _generator.init(new SecureRandom(strKey.getBytes()));
       SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );  
       secureRandom.setSeed(strKey.getBytes());  

       _generator.init(secureRandom);  
       
       this.key = _generator.generateKey();
       _generator = null;
      } catch (Exception e) {        
          e.printStackTrace();
      }
     }
     原因是

SecureRandom 实现完全隨操作系统本身的內部狀態,除非調用方在調用 getInstance 方法之後又調用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。
参考:http://blog.csdn.net/hbcui1984/article/details/5753083

你可能感兴趣的:(SSH,java,linux)