do not log passwords

This commit is contained in:
Jörg Prante 2022-10-30 23:00:18 +01:00
parent 7378b91c28
commit 6127f11914
7 changed files with 72 additions and 23 deletions

View file

@ -379,7 +379,7 @@ public class Pool implements BagStateListener {
} }
/** /**
* Recycle PoolEntry (add back to the pool) * Recycle PoolEntry, add back to the pool.
* *
* @param poolEntry the PoolEntry to recycle * @param poolEntry the PoolEntry to recycle
*/ */
@ -957,7 +957,7 @@ public class Pool implements BagStateListener {
writeMethod.invoke(target, Class.forName(propValue.toString()).getDeclaredConstructor().newInstance()); writeMethod.invoke(target, Class.forName(propValue.toString()).getDeclaredConstructor().newInstance());
} catch (InstantiationException | ClassNotFoundException e) { } catch (InstantiationException | ClassNotFoundException e) {
logger.log(Level.FINE, () -> logger.log(Level.FINE, () ->
MessageFormat.format("class not found or could not instantiate it (Default constructor): {0}", MessageFormat.format("class not found or could not instantiate it (default constructor): {0}",
propValue)); propValue));
writeMethod.invoke(target, propValue); writeMethod.invoke(target, propValue);
} }

View file

@ -567,11 +567,11 @@ public class PoolConfig {
this.threadFactory = threadFactory; this.threadFactory = threadFactory;
} }
private Class<?> attemptFromContextLoader(final String driverClassName) { private Class<?> attemptFromContextLoader(String driverClassName) {
final ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
if (threadContextClassLoader != null) { if (threadContextClassLoader != null) {
try { try {
final Class<?> driverClass = threadContextClassLoader.loadClass(driverClassName); Class<?> driverClass = threadContextClassLoader.loadClass(driverClassName);
logger.log(Level.FINE, "Driver class found in Thread context class loader:" + logger.log(Level.FINE, "Driver class found in Thread context class loader:" +
driverClassName + " " + threadContextClassLoader); driverClassName + " " + threadContextClassLoader);
return driverClass; return driverClass;
@ -580,7 +580,6 @@ public class PoolConfig {
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader()); driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
} }
} }
return null; return null;
} }
@ -622,7 +621,7 @@ public class PoolConfig {
/** /**
* @return null if string is null or empty * @return null if string is null or empty
*/ */
private static String getNullIfEmpty(final String text) { private static String getNullIfEmpty(String text) {
return text == null ? null : text.trim().isEmpty() ? null : text.trim(); return text == null ? null : text.trim().isEmpty() ? null : text.trim();
} }

View file

@ -40,7 +40,7 @@ public class PoolEntry implements BagEntry {
private final boolean isAutoCommit; private final boolean isAutoCommit;
public PoolEntry(Connection connection, Pool pool, final boolean isReadOnly, final boolean isAutoCommit) { public PoolEntry(Connection connection, Pool pool, boolean isReadOnly, boolean isAutoCommit) {
this.connection = connection; this.connection = connection;
this.pool = pool; this.pool = pool;
this.isReadOnly = isReadOnly; this.isReadOnly = isReadOnly;
@ -70,7 +70,7 @@ public class PoolEntry implements BagEntry {
* *
* @param lastAccessed last access time-stamp * @param lastAccessed last access time-stamp
*/ */
public void recycle(final long lastAccessed) { public void recycle(long lastAccessed) {
if (connection != null) { if (connection != null) {
this.lastAccessed = lastAccessed; this.lastAccessed = lastAccessed;
pool.recycle(this); pool.recycle(this);
@ -82,11 +82,11 @@ public class PoolEntry implements BagEntry {
* *
* @param endOfLife this PoolEntry/Connection's end of life {@link ScheduledFuture} * @param endOfLife this PoolEntry/Connection's end of life {@link ScheduledFuture}
*/ */
public void setFutureEol(final ScheduledFuture<?> endOfLife) { public void setFutureEol(ScheduledFuture<?> endOfLife) {
this.endOfLife = endOfLife; this.endOfLife = endOfLife;
} }
public Connection createProxyConnection(final ProxyLeakTask leakTask, final long now) { public Connection createProxyConnection(ProxyLeakTask leakTask, long now) {
return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now, isReadOnly, isAutoCommit); return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now, isReadOnly, isAutoCommit);
} }
@ -102,7 +102,7 @@ public class PoolEntry implements BagEntry {
this.evict = true; this.evict = true;
} }
public void evict(final String closureReason) { public void evict(String closureReason) {
pool.closeConnection(this, closureReason); pool.closeConnection(this, closureReason);
} }

View file

@ -17,15 +17,15 @@ import java.util.stream.Collectors;
* This is a specialized concurrent bag that achieves superior performance * This is a specialized concurrent bag that achieves superior performance
* to {@link java.util.concurrent.LinkedBlockingQueue} and * to {@link java.util.concurrent.LinkedBlockingQueue} and
* {@link java.util.concurrent.LinkedTransferQueue} for the purposes of a * {@link java.util.concurrent.LinkedTransferQueue} for the purposes of a
* connection pool. It uses {@link ThreadLocal} storage when possible to avoid * connection pool. It uses {@link ThreadLocal} storage when possible to avoid
* locks, but resorts to scanning a common collection if there are no * locks, but resorts to scanning a common collection if there are no
* available items in the {@link ThreadLocal} list. Not-in-use items in the * available items in the {@link ThreadLocal} list. Not-in-use items in the
* {@link ThreadLocal} lists can be "stolen" when the borrowing thread has none * {@link ThreadLocal} lists can be "stolen" when the borrowing thread has none
* of its own. It is a "lock-less" implementation using a specialized * of its own. It is a "lock-less" implementation using a specialized
* {@link AbstractQueuedLongSynchronizer} to manage cross-thread signaling. * {@link AbstractQueuedLongSynchronizer} to manage cross-thread signaling.
* Note that items that are "borrowed" from the bag are not actually * Note that items that are "borrowed" from the bag are not actually
* removed from any collection, so garbage collection will not occur * removed from any collection, so garbage collection will not occur
* even if the reference is abandoned. Thus care must be taken to * even if the reference is abandoned. Thus care must be taken to
* {@link Bag#requite(T)} borrowed objects otherwise a memory leak will result. * {@link Bag#requite(T)} borrowed objects otherwise a memory leak will result.
* Only the {@link Bag#remove(T)} method can completely remove an object. * Only the {@link Bag#remove(T)} method can completely remove an object.
* *

View file

@ -143,9 +143,15 @@ public interface ClockSource {
return sb.toString(); return sb.toString();
} }
TimeUnit[] TIMEUNITS_DESCENDING = {TimeUnit.DAYS, TimeUnit.HOURS, TimeUnit.MINUTES, TimeUnit[] TIMEUNITS_DESCENDING = {
TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.DAYS,
TimeUnit.NANOSECONDS}; TimeUnit.HOURS,
TimeUnit.MINUTES,
TimeUnit.SECONDS,
TimeUnit.MILLISECONDS,
TimeUnit.MICROSECONDS,
TimeUnit.NANOSECONDS
};
String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"}; String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"};

View file

@ -78,16 +78,16 @@ public class DriverDataSource implements DataSource {
} }
} }
} }
final String sanitizedUrl = jdbcUrl.replaceAll("([?&;]password=)[^&#;]*(.*)", "$1<masked>$2"); final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1<masked>");
try { try {
if (driver == null) { if (driver == null) {
driver = DriverManager.getDriver(jdbcUrl); driver = DriverManager.getDriver(jdbcUrl);
logger.fine("Loaded driver with class name for jdbcUrl: " + driver.getClass().getName() + " " + sanitizedUrl); logger.fine("Loaded driver with class name for jdbcUrl " + driver.getClass().getName() + " " + sanitizedUrl);
} else if (!driver.acceptsURL(jdbcUrl)) { } else if (!driver.acceptsURL(jdbcUrl)) {
throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl, " + sanitizedUrl); throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl);
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException("Failed to get driver instance for jdbcUrl=" + sanitizedUrl, e); throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e);
} }
} }

View file

@ -0,0 +1,44 @@
package org.xbib.io.pool.jdbc;
import org.junit.jupiter.api.Test;
import org.xbib.jdbc.connection.pool.util.DriverDataSource;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class DriverDataSourceTest {
@Test
public void testJdbcUrlLogging() {
List<String> urls = Arrays.asList(
"jdbc:invalid://host/d_dlq?user=USER&password=SECRET",
"jdbc:invalid://host/d_dlq?user=USER&truststorePassword=SECRET",
"jdbc:invalid://host/d_dlq?a=b&password=SECRET&user=USER",
"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&user=USER",
"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&password=SECRET&user=USER",
"jdbc:invalid://host/d_dlq?truststorePassword=SECRET;user=USER&password=SECRET#extra",
"jdbc:invalid://host/d_dlq?sslpassword=SECRET&password=SECRET&trustPassword=SECRET&user=USER",
"jdbc:invalid://host/d_dlq?password=SECRET#user=USER;extra"
);
for (String url : urls) {
testExceptionMessage(url);
}
}
private void testExceptionMessage(String jdbcUrl) {
try {
new DriverDataSource(jdbcUrl, null, new Properties(), null, null);
fail();
} catch (RuntimeException e) {
String msg = e.getMessage();
assertTrue(msg.contains("jdbc:invalid://host/d_dlq"));
assertTrue(msg.contains("user=USER"));
assertFalse(msg.contains("SECRET"));
}
}
}