Added DBAuthenticator & Test with H2 DB
This commit is contained in:
@@ -137,6 +137,12 @@
|
||||
<version>9.2.0.M1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.191</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package io.moquette.spi.impl.security;
|
||||
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* Load user credentials from a SQL database.
|
||||
* sql driver must be provided at runtime
|
||||
*
|
||||
* @author mackristof
|
||||
*/
|
||||
|
||||
public class DBAuthenticator implements IAuthenticator {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DBAuthenticator.class);
|
||||
|
||||
private final String sqlQuery;
|
||||
private final MessageDigest messageDigest;
|
||||
private final PreparedStatement preparedStatement;
|
||||
|
||||
|
||||
/** provide authenticator from SQL database
|
||||
* @param driver : jdbc driver class like : "org.postgresql.Driver"
|
||||
* @param jdbcUrl : jdbc url like : "jdbc:postgresql://host:port/dbname"
|
||||
* @param sqlQuery : sql query like : "SELECT PASSWORD FROM USER WHERE LOGIN=?"
|
||||
* @param digestMethod : password encoding algorithm : "MD5", "SHA-1", "SHA-256"
|
||||
*/
|
||||
public DBAuthenticator(String driver, String jdbcUrl, String sqlQuery, String digestMethod){
|
||||
|
||||
this.sqlQuery = sqlQuery;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean checkValid(String username, byte[] password) {
|
||||
// Check Username / Password in DB using sqlQuery
|
||||
if (username == null || password == null) {
|
||||
LOG.info("username or password was null");
|
||||
return false;
|
||||
}
|
||||
ResultSet r= null;
|
||||
try {
|
||||
this.preparedStatement.setString(1,username);
|
||||
r = this.preparedStatement.executeQuery();
|
||||
if(r.next()) {
|
||||
final String foundPwq = r.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();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
this.preparedStatement.close();
|
||||
this.preparedStatement.getConnection().close();
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package io.moquette.spi.impl.security;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.junit.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.*;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by mackristof on 12/05/2016.
|
||||
*/
|
||||
public class DBAuthenticatorTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DBAuthenticatorTest.class);
|
||||
|
||||
public static final String ORG_H2_DRIVER = "org.h2.Driver";
|
||||
public static final String JDBC_H2_MEM_TEST = "jdbc:h2:mem:test";
|
||||
public static final String SHA_256 = "SHA-256";
|
||||
private Connection connection;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws ClassNotFoundException, SQLException, NoSuchAlgorithmException {
|
||||
Class.forName(ORG_H2_DRIVER);
|
||||
this.connection = DriverManager.getConnection(JDBC_H2_MEM_TEST);
|
||||
Statement statement = this.connection.createStatement();
|
||||
try {
|
||||
statement.execute("DROP TABLE USER");
|
||||
} catch(SQLException sqle) {
|
||||
LOG.info("Table not found, not dropping",sqle);
|
||||
}
|
||||
MessageDigest digest = MessageDigest.getInstance(SHA_256);
|
||||
String hash = new String(Hex.encodeHex(digest.digest("password".getBytes(StandardCharsets.UTF_8))));
|
||||
try {
|
||||
if (statement.execute("CREATE TABLE PUBLIC.USER ( LOGIN VARCHAR(64), PASSWORD VARCHAR(256))")){
|
||||
throw new SQLException("can't create USER table");
|
||||
}
|
||||
if (statement.execute("INSERT INTO PUBLIC.USER ( LOGIN , PASSWORD ) VALUES ('testuser', '"+hash+"')")){
|
||||
throw new SQLException("can't insert in USER table");
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
LOG.error("Table not created, not inserted",sqle);
|
||||
return;
|
||||
}
|
||||
LOG.info("Table User created");
|
||||
statement.close();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Db_verifyValid() {
|
||||
final DBAuthenticator dbAuthenticator = new DBAuthenticator(ORG_H2_DRIVER, JDBC_H2_MEM_TEST, "SELECT PASSWORD FROM USER WHERE LOGIN=?", SHA_256);
|
||||
assertTrue(dbAuthenticator.checkValid("testuser","password".getBytes()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Db_verifyInvalid(){
|
||||
final DBAuthenticator dbAuthenticator = new DBAuthenticator(ORG_H2_DRIVER, JDBC_H2_MEM_TEST, "SELECT PASSWORD FROM USER WHERE LOGIN=?", SHA_256);
|
||||
assertFalse(dbAuthenticator.checkValid("testuser2","password".getBytes()));
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void teardown(){
|
||||
try {
|
||||
this.connection.close();
|
||||
} catch (SQLException e) {
|
||||
LOG.error("can't close connection",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user