Issue
I am using an Spring bean to set a JDBC pool connection to a mySql server. This includes setting a custom DataSource to set my own password encryption.
package com.mypackage;
import org.apache.tomcat.jdbc.pool.DataSource;
public class CustomDataSource extends DataSource {
public void setPassword(String encodedPassword){
Crypt crypt = new Crypt();
String decodePassword = crypt.decryptValue(encodedPassword);
getPoolProperties().setPassword(decodePassword);
}
}
The bean is configured this way:
<bean id="MySQLSource" class="com.mypackage.CustomDataSource" destroy-method="close" >
<property name="url" value="jdbc:mysql://127.0.0.1:3306/dbname?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=GMT"/>
<property name="username" value="dbuser"/>
<property name="password" value="E5EDF4AE2517F5F69417CF9496FCC6ED065F6542003956B2BDDA6CFD" />
<property name="initialSize" value="10" />
<property name="maxActive" value="100" />
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="15" />
<property name="logAbandoned" value="true" />
<property name="validationQuery" value="Select 1" />
<property name="testOnBorrow" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="10000" />
</bean>
This configuration works in Tomcat8 in servers with Ubuntu 18.6 and 20.4. Also works in Tomcat8 and Tomcat9 on Eclipse on a MacOS laptop which I use for testing. These use OpenJDK9.
However, I have another server with Ubuntu 20.4 with Tomcat9 using OpenJDK11 and in this case this setup does not work. It shows the error:
03-Oct-2021 22:39:26.892 WARNING [ajp-nio-127.0.0.1-8009-exec-2] org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver Not loading a JDBC driver as driverClassName property is null.
03-Oct-2021 22:39:27.145 SEVERE [ajp-nio-127.0.0.1-8009-exec-2] org.apache.tomcat.jdbc.pool.ConnectionPool.init Unable to create initial connections of pool.
java.sql.SQLException: Access denied for user 'silkbuilder'@'localhost' (using password: YES)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:189)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:317)
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212)
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:744)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:676)
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483)
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
However, when I set a non-encrypted password in the bean's configuration it works as it should be:
<property name="password" value="no-encrypted-password" />
So, in this case it seems like the bean is ignoring "com.mypackage.CustomDataSource" and is using "org.apache.tomcat.jdbc.pool.DataSource" directly.
I have also modify the CustomeDataSource to display the unencrypted password in the catalina log:
package com.mypackage;
import org.apache.tomcat.jdbc.pool.DataSource;
public class CustomDataSource extends DataSource {
public void setPassword(String encodedPassword){
Crypt crypt = new Crypt();
String decodePassword = crypt.decryptValue(encodedPassword);
System.out.println("pwd:"++decodePassword); //<--This is new
getPoolProperties().setPassword(decodePassword);
}
}
In the other servers I can see the password in the catalina log as it should be. However in the Ubuntu 20.4 with Tomcat9 it does not show the password in the catalina log.
I could set the server with a plain password and ignore the issue. But I want to have this server with an encrypted db password as the rest.
Thank you for any help.
Solution
Your custom class overriddes the setPassword
method, but contains only half of the operations of the original method:
public void setPassword(String password) {
this.poolProperties.setPassword(password);
this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());
}
When overriding methods you should always consider calling the overridden method, by using the keyword super
:
@Override
public void setPassword(String encodedPassword){
Crypt crypt = new Crypt();
String decodePassword = crypt.decryptValue(encodedPassword);
super.setPassword(decodePassword);
}
Answered By - Piotr P. Karwasz