如何避免在tomcat的server.xml数据源的资源定义中明文存储密码?
时间:2020-03-06 14:40:58 来源:igfitidea点击:
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"/>
密码是明文的。如何避免这种情况?
解决方案
我们使用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;
});
)
Tomcat需要知道如何连接到数据库,因此需要访问纯文本密码。如果密码是加密的,则Tomcat需要知道如何解密它,因此我们只是将问题移到了其他地方。
真正的问题是:除了Tomcat之外,谁还能访问server.xml?一种解决方案是仅向root用户授予对server.xml的读取访问权限,这要求Tomcat以root特权启动:如果恶意用户在系统上获得root特权,则丢失数据库密码可能是一个小问题。
否则,我们应该在每次启动时手动键入密码,但这很少是一个可行的选择。
如前所述,加密密码只是将问题转移到其他地方。
无论如何,这很简单。
只需编写一个类,其中包含用于密钥的静态字段等,以及用于加密,解密密码的静态方法。
使用此类将密码加密在Tomcat的配置文件(" server.xml"或者" yourapp.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;
}
}
希望这可以帮助。

