讀取項目中properties文件中的賬號密碼進行加密解密

項目需求 :

所有認證數據,例如密碼,不論是在儲存、傳輸中都必須妥善保護,以防泄露或被未獲授權修改。在安全認證中的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.

<bean id="dataSource" class="com.ncs.pki.util.MyBasicDataSource" destroy-method="close">
        <property name="driverClassName">
            <value>oracle.jdbc.driver.OracleDriver</value>
        </property>
        <property name="url">
            <value>jdbc:oracle:thin:@dbServer:1521:feelview</value>
        </property>
        <property name="username">
            <value>feelview</value>
        </property>
        <property name="password">
            <value>${jdbc.password}value>
        </property>
    </bean> 


 

解析:

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
發佈了22 篇原創文章 · 獲贊 35 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章