From ba2b8b44d3a93ab4498480e33016605791500406 Mon Sep 17 00:00:00 2001 From: andsel Date: Fri, 20 Oct 2017 12:25:10 +0200 Subject: [PATCH] Fixed issue #360, used a DB connection pool instead of long lasting Drivers connections --- broker/build.gradle | 2 + .../spi/impl/security/DBAuthenticator.java | 73 +++++++++++-------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/broker/build.gradle b/broker/build.gradle index 13e1fab1..2451c447 100644 --- a/broker/build.gradle +++ b/broker/build.gradle @@ -13,6 +13,8 @@ dependencies { compile group: 'io.netty', name: 'netty-transport-native-epoll', version: nettyVersion, classifier: 'linux-x86_64' // ${os.detected.name}-${os.detected.arch} + compile group: 'com.zaxxer', name: 'HikariCP', version:'2.4.7' + compile group: 'io.dropwizard.metrics', name: 'metrics-core', version:'3.2.2' compile group: 'io.dropwizard.metrics', name: 'metrics-jvm', version:'3.2.2' diff --git a/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java b/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java index 5fcf30f5..3ef49037 100644 --- a/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java +++ b/broker/src/main/java/io/moquette/spi/impl/security/DBAuthenticator.java @@ -16,15 +16,20 @@ package io.moquette.spi.impl.security; +import com.zaxxer.hikari.HikariDataSource; import io.moquette.BrokerConstants; import io.moquette.server.config.IConfig; import io.moquette.spi.security.IAuthenticator; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.sql.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; /** * Load user credentials from a SQL database. sql driver must be provided at runtime @@ -34,14 +39,14 @@ public class DBAuthenticator implements IAuthenticator { private static final Logger LOG = LoggerFactory.getLogger(DBAuthenticator.class); private final MessageDigest messageDigest; - private final PreparedStatement preparedStatement; + private HikariDataSource dataSource; + private String sqlQuery; public DBAuthenticator(IConfig conf) { - this( - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DRIVER, ""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_URL, ""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_QUERY, ""), - conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DIGEST, "")); + this(conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DRIVER, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_URL, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_QUERY, ""), + conf.getProperty(BrokerConstants.DB_AUTHENTICATOR_DIGEST, "")); } /** @@ -57,18 +62,12 @@ public class DBAuthenticator implements IAuthenticator { * : password encoding algorithm : "MD5", "SHA-1", "SHA-256" */ public DBAuthenticator(String driver, String jdbcUrl, String sqlQuery, String digestMethod) { + this.sqlQuery = sqlQuery; + this.dataSource = new HikariDataSource(); + this.dataSource.setJdbcUrl(jdbcUrl); try { - Class.forName(driver); - final Connection connection = DriverManager.getConnection(jdbcUrl); this.messageDigest = MessageDigest.getInstance(digestMethod); - this.preparedStatement = connection.prepareStatement(sqlQuery); - } catch (ClassNotFoundException cnfe) { - LOG.error(String.format("Can't find driver %s", driver), cnfe); - throw new RuntimeException(cnfe); - } catch (SQLException sqle) { - LOG.error(String.format("Can't connect to %s", jdbcUrl), sqle); - throw new RuntimeException(sqle); } catch (NoSuchAlgorithmException nsaex) { LOG.error(String.format("Can't find %s for password encoding", digestMethod), nsaex); throw new RuntimeException(nsaex); @@ -82,28 +81,40 @@ public class DBAuthenticator implements IAuthenticator { LOG.info("username or password was null"); return false; } - ResultSet r = null; + + ResultSet resultSet = null; + PreparedStatement preparedStatement = null; + Connection conn = null; try { - this.preparedStatement.setString(1, username); - r = this.preparedStatement.executeQuery(); - if (r.next()) { - final String foundPwq = r.getString(1); + conn = this.dataSource.getConnection(); + + preparedStatement = conn.prepareStatement(this.sqlQuery); + preparedStatement.setString(1, username); + resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + final String foundPwq = resultSet.getString(1); messageDigest.update(password); byte[] digest = messageDigest.digest(); String encodedPasswd = new String(Hex.encodeHex(digest)); return foundPwq.equals(encodedPasswd); } - r.close(); - } catch (SQLException e) { - e.printStackTrace(); + } catch (SQLException sqlex) { + LOG.error("Error quering DB for username: {}", username, sqlex); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + if (preparedStatement != null) { + preparedStatement.close(); + } + if (conn != null) { + conn.close(); + } + } catch (SQLException e) { + LOG.error("Error releasing connection to the datasource", username, e); + } } return false; } - - @Override - protected void finalize() throws Throwable { - this.preparedStatement.close(); - this.preparedStatement.getConnection().close(); - super.finalize(); - } }