问题
As the title says, I'm looking into finding a way to use a char[] array to establish a JDBC connection instead of creating a new String object from the char[] array and using that to establish the connection.
Because char[] arrays are more secure than Strings in java, I've been wanting to keep things as secure as possible when dealing with my JPasswordFields.
In this particular case, I'm taking the char[] array contents of a JPasswordField and attempting to establish a JDBC connection to a database. It works perfectly well, but I'm having to create a new String object from the char[] array to actually call the getConnection method.
Is there any way to ensure at-least some security doing this, or am I just forced to create the String object and continue on using that in the method?
This is my code:
/**
* Construct a new DataManager object with it's own
* connection to the database.
*
* @param ipAddress The IP address to the server on which MySQL is running.
* @param port The port to use when connecting to MySQL.
* @param databaseName The database name of the database to connect to.
* @param username The username for a MySQL account with access to the specified database.
* @param password The password for the MySQL account specified by the specified username.
*/
public DataManager(final String ipAddress, final String port, final String databaseName, final String username, final char[] password) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://" + ipAddress + ":" + port + "/" + databaseName + "?noAccessToProcedureBodies=true"; //?noAccessToProcedureBodies=true is required for using the stored procedures.
dbConnection = DriverManager.getConnection(url, username, new String(password));
}
Sorry for the formatting, but the lines are a bit long and they wrap.
Here's the Java docs for the DriverManager class that I'm using. I've checked and there doesn't seem to be a method to use the char[]
instead of the String
and that's what prompted this post.
Thanks for any help/tips.
回答1:
As @DavidS said in the comments, I'm not sure using a char[] is really more secure in a meaningful way, but I did dig into the the DriverManager
source to see if it was possible to use anyway.
If you look at the getConnection() method you're using you'll see that it (along with the other parameter variations) is collecting all the provided connection information in a java.util.Properties, which is essentially a String->String hash table. The Properties object is then passed to the needed driver on a method that's defined as part of the long standing (and thus very unlikely to change) java.sql.Driver interface, with any implementation of that obviously dependent on the driver.
At that point I think you have to automatically assume that someone somewhere will either make a copy of the supplied password String or include it in the composition of a bigger String, and so you can't rely on reflection to go back and clear out that buffer. For example, in the PostgreSQL JDBC driver, depending on your authentication settings the password may just be sitting out as an encoded byte[] and even the settings that digest it still possibly (I haven't looked too extensively, and I'm not trying to knock PostgreSQL here) leave that digest open to being dug up.
Even if no one ever made a copy of the password String and the digest was completely untouchable, you still have to worry about the fact that there are dangling references to the it (through the Properties object) all over your driver's stack, and things might break in unexpected ways.
For better or worse, I think we're pretty committed to storing DB passwords as Strings at this point, but I'm really not convinced it's a big issue. I don't think the historical experience has been that it's easier for programmers to securely manage the life-cycle of sensitive objects as opposed to the garbage collector. It'd be nice if Java gave us a way to annotate an object as a target for more aggressive pruning, but also probably not necessary.
Just writing this post, I had to go through ~8 levels of method calls and object creation and so I wonder if the password string is really short-lived enough that being able to manually wipe it would significantly decrease attack surface area. I think the convenience as ergonomics of Java's DB handling lets us forget how much is going on behind the scenes.
来源:https://stackoverflow.com/questions/31280729/issue-establishing-a-database-connection-with-a-char-array-instead-of-a-string