如何避免在tomcat的server.xml中以明文形式存储密码?DataSource的资源定义?

dac*_*cot 38 configuration tomcat jdbc

tomcat中的资源定义server.xml看起来像这样......

<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"/>
Run Code Online (Sandbox Code Playgroud)

密码是明确的.怎么避免这个?

小智 39

如前所述,加密密码只是将问题转移到其他地方.

无论如何,这很简单.只需为您的密钥等编写一个包含静态字段的类,然后使用静态方法加密,解密您的密码.使用此类在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://..."/>
Run Code Online (Sandbox Code Playgroud)

而对于定制工厂:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • IMO它仍然比明确的密码更好,每个愚蠢的脚本小子将知道寻找它.它提高了一些吧,不是吗? (7认同)
  • 对我来说,这并没有增加任何安全性,因为攻击者总是可以反编译你的jar来获取你在类文件中硬编码的密码...... (6认同)

Rya*_*yan 10

Tomcat有一个密码常见问题解答专门解决您的问题.简而言之:保持密码清晰并正确锁定服务器.

该页面还提供了一些关于如何使用默示安全性来传递审核员清单的建议.

  • 尽管如此,您可能还是希望将包含密码的文件与其余配置分开保存。在某些情况下,人们希望将配置文件放入某个版本控制系统中,该版本控制系统对于所有相关开发人员,不仅是系统管理员,都是可读的。 (2认同)

Jus*_*KSU 5

正如 @Ryan 提到的,在实施此解决方案之前,请阅读 Tomcat 的Tomcat 密码常见问题解答。您只是增加了模糊性,而不是增加了安全性。

@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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

原子示例:

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新参考中的密码值:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦包含这些类的 .jar 文件位于 Tomcat 的类路径中,您就可以更新 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... />
Run Code Online (Sandbox Code Playgroud)


Bra*_*118 -9

我们使用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;
        });
Run Code Online (Sandbox Code Playgroud)

  • 不确定这与 tomcat 配置文件有什么关系。 (3认同)