2008-09-24 26 views
32

Tomcat的server.xml資源定義看起來是這樣的......如何避免爲tomcat的server.xml中的明文存儲密碼DataSource的資源定義?

<Resource 
    name="jdbc/tox" 
    scope="Shareable" 
    type="javax.sql.DataSource" 
    url="jdbc:oracle:thin:@yourDBserver.yourCompany.com:1521:yourDBsid" 
    driverClassName="oracle.jdbc.pool.OracleDataSource" 
    username="tox" 
    password="toxbaby" 
    maxIdle="3" 
    maxActive="10" 
    removeAbandoned="true" 
    removeAbandonedTimeout="60" 
    testOnBorrow="true" 
    validationQuery="select * from dual" 
    logAbandoned="true" 
    debug="99"/> 

的密碼是明文的。如何避免這種情況?

回答

-8

我們使用C#的SHA1CryptoServiceProvider

print(SHA1CryptoServiceProvider sHA1Hasher = new SHA1CryptoServiceProvider(); 
     ASCIIEncoding enc = new ASCIIEncoding(); 

     byte[] arrbytHashValue = sHA1Hasher.ComputeHash(enc.GetBytes(clearTextPW)); 
     string HashData = System.BitConverter.ToString(arrbytHashValue); 
     HashData = HashData.Replace("-", ""); 
     if (HashData == databaseHashedPassWO) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     }); 

+2

不知道這與Tomcat的配置文件做。 – dacracot 2008-09-24 19:27:26

3

的Tomcat需要知道如何連接到數據庫,所以它需要訪問明文密碼。如果密碼是加密的,那麼Tomcat需要知道如何解密,所以你只能把問題轉移到其他地方。

真正的問題是:除了Tomcat,誰可以訪問server.xml?一種解決方案是僅爲root用戶提供對server.xml的讀取訪問權限,要求Tomcat以root權限啓動:如果惡意用戶獲得系統上的root權限,則丟失數據庫密碼可能是次要問題。

否則,您應該在每次啓動時手動輸入密碼,但這很少是可行的選項。

+1

我並不是一名安全專家,但在我看來,Tomcat本身就是攻擊的可能入口之一(通過Tomcat本身或應用程序使用的某個庫的漏洞利用,例如最近Struts 2的問題),因此不應該給予root權限! – 2014-03-06 15:09:12

+0

我同意。我不再使用Tomcat,但我會建議在沒有root權限的情況下運行它。 不管怎樣,誰可以讀取tomcat目錄,都可以讀取DB密碼。據我所知,這是使用任何語言/框架的不可避免的問題。 – gameame 2014-03-14 11:23:28

+5

這是一個可憐的答案,爲什麼我的腦海裏會出現反對票。保持安全。是的,如果可以的話,加密密碼,否則你不必以root身份運行tomcat(不僅是壞的,但是這個陳述是一個錯誤的假設,你必須)。訪問系統,丟失密碼或輕易發現密碼是一個主要問題,因爲黑客可能在一段時間內未被檢測到,並且您的數據庫可能包含敏感數據。數據庫是系統中的創業板,也是人們試圖破解你的盒子的主要原因。 – 2014-10-13 18:47:04

35

正如之前所說的,加密密碼只是將問題轉移到其他地方。

無論如何,這很簡單。 只需用靜態字段爲您的密鑰編寫一個類等等,然後使用靜態方法來加密,解密您的密碼。 使用此類在Tomcat的配置文件(server.xmlyourapp.xml ...)中加密密碼。

爲了在Tomcat中「即時」解密密碼,請擴展DBCP的BasicDataSourceFactory並在您的資源中使用此工廠。

它看起來像:

<Resource 
     name="jdbc/myDataSource" 
     auth="Container" 
     type="javax.sql.DataSource" 
     username="user" 
     password="encryptedpassword" 
     driverClassName="driverClass" 
     factory="mypackage.MyCustomBasicDataSourceFactory" 
     url="jdbc:blabla://..."/> 

而對於工廠定製:

package mypackage; 

.... 

public class MyCustomBasicDataSourceFactory extends org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory { 

@Override 
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { 
    Object o = super.getObjectInstance(obj, name, nameCtx, environment); 
    if (o != null) { 
     BasicDataSource ds = (BasicDataSource) o; 
     if (ds.getPassword() != null && ds.getPassword().length() > 0) { 
      String pwd = MyPasswordUtilClass.unscramblePassword(ds.getPassword()); 
      ds.setPassword(pwd); 
     } 
     return ds; 
    } else { 
     return null; 
    } 
} 

希望這有助於。

+6

對我來說,這並沒有增加任何安全性,因爲攻擊者總是可以反編譯你的jar來獲得你在類文件中硬編碼的密碼。 – dmansfield 2012-06-26 16:04:34

+5

海事組織它仍然比在每個笨笨的腳本小子會知道尋找它的明確密碼更好。它提出了一些吧,不是嗎? – 2014-02-28 09:15:18

5

Tomcat有a Password FAQ專門解決您的問題。簡而言之:保持密碼清晰並正確鎖定您的服務器。

該頁面還提供了一些關於如何使用默認安全性來通過審覈員清單的建議。

3

正如@Ryan提到的,在實施此解決方案之前,請閱讀Tomcat的Tomcat Password FAQ。你只是添加了默默無聞的安全性。

@Jerome Delattre的答案適用於簡單的JDBC數據源,但不適用於作爲數據源構造一部分連接的更復雜的數據源(例如oracle.jdbc.xa.client.OracleXADataSource)。

這是在調用現有工廠之前修改密碼的替代方法。下面是基本數據源的工廠示例,以及Atomikos JTA兼容XA數據源的示例。

基本示例:

public class MyEncryptedPasswordFactory extends BasicDataSourceFactory { 

    @Override 
    public Object getObjectInstance(Object obj, Name name, Context context, Hashtable<?, ?> environment) 
      throws Exception { 
     if (obj instanceof Reference) { 
      Reference ref = (Reference) obj; 
      DecryptPasswordUtil.replacePasswordWithDecrypted(ref, "password"); 
      return super.getObjectInstance(obj, name, context, environment); 
     } else { 
      throw new IllegalArgumentException(
        "Expecting javax.naming.Reference as object type not " + obj.getClass().getName()); 
     } 
    } 
} 

Atomikos公司舉例:

public class MyEncryptedAtomikosPasswordFactory extends EnhancedTomcatAtomikosBeanFactory { 
    @Override 
    public Object getObjectInstance(Object obj, Name name, Context context, Hashtable<?, ?> environment) 
      throws NamingException { 
     if (obj instanceof Reference) { 
      Reference ref = (Reference) obj; 
      DecryptPasswordUtil.replacePasswordWithDecrypted(ref, "xaProperties.password"); 
      return super.getObjectInstance(obj, name, context, environment); 
     } else { 
      throw new IllegalArgumentException(
        "Expecting javax.naming.Reference as object type not " + obj.getClass().getName()); 
     } 
    } 
} 

更新參考密碼值:

public class DecryptPasswordUtil { 

    public static void replacePasswordWithDecrypted(Reference reference, String passwordKey) { 
     if(reference == null) { 
      throw new IllegalArgumentException("Reference object must not be null"); 
     } 

     // Search for password addr and replace with decrypted 
     for (int i = 0; i < reference.size(); i++) { 
      RefAddr addr = reference.get(i); 
      if (passwordKey.equals(addr.getType())) { 
       if (addr.getContent() == null) { 
        throw new IllegalArgumentException("Password must not be null for key " + passwordKey); 
       } 
       String decrypted = yourDecryptionMethod(addr.getContent().toString()); 
       reference.remove(i); 
       reference.add(i, new StringRefAddr(passwordKey, decrypted)); 
       break; 
      } 
     } 
    } 
} 

一旦包含這些類的.jar文件在Tomcat的classpath中你可以更新你的server.xml來使用它們。

<Resource factory="com.mycompany.MyEncryptedPasswordFactory" username="user" password="encryptedPassword" ...other options... /> 

<Resource factory="com.mycompany.MyEncryptedAtomikosPasswordFactory" type="com.atomikos.jdbc.AtomikosDataSourceBean" xaProperties.user="user" xaProperties.password="encryptedPassword" ...other options... /> 
-1

所有前述雖如此,如果仍然希望避免可以使用散列算法,例如SHA-256或(優選地)SHA-512的純文本的密碼。當創建密碼時,獲取哈希值並存儲它而不是密碼。當用戶登錄時,散列密碼並查看它與存儲的散列密碼相匹配。 散列算法將一個字符串(或數字)從一個小的字符串(或數字)空間轉換成一個更大的字符串,而這種方式的反向代價很高。

0

Here是一步一步的指導,基本上你需要編寫你自己的數據源工廠,並在初始化數據源時解密數據庫憑證,希望鏈接有幫助。

1

經過4個小時的工作,搜索問題和答案我得到了解決方案。 基於@Jerome Delattre的回答,這裏是完整的代碼(使用JNDI數據源配置)。

的context.xml

<Resource 
    name="jdbc/myDataSource" 
    auth="Container" 
    type="javax.sql.DataSource" 
    username="user" 
    password="encryptedpassword" 
    driverClassName="driverClass" 
    factory="mypackage.MyCustomBasicDataSourceFactory" 
    url="jdbc:blabla://..."/> 

自定義數據源廠:

package mypackage; 

public class MyCustomBasicDataSourceFactory extends org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory { 
    @Override 
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { 
     Object o = super.getObjectInstance(obj, name, nameCtx, environment); 
     if (o != null) { 
      BasicDataSource ds = (BasicDataSource) o; 
      if (ds.getPassword() != null && ds.getPassword().length() > 0) { 
       String pwd = MyPasswordUtilClass.unscramblePassword(ds.getPassword()); 
       ds.setPassword(pwd); 
      } 
      return ds; 
     } else { 
      return null; 
     } 
    } 
} 

數據源的bean:

@Bean 
public DataSource dataSource() { 
    DataSource ds = null; 
    JndiTemplate jndi = new JndiTemplate(); 
    try { 
     ds = jndi.lookup("java:comp/env/jdbc/myDataSource", DataSource.class); 
    } catch (NamingException e) { 
     log.error("NamingException for java:comp/env/jdbc/myDataSource", e); 
    } 
    return ds; 
} 
相關問題