I am building a web application with java and using JDBC driver
please tell me if i wrong, i dont think using this block of code is secured
how should i make it secured without using "HARD CODED" password
Connection connection = null;
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:mkyong","username","password");
connection.close();
taken from:
http://www.mkyong.com/jdbc/connect-to-oracle-db-via-jdbc-driver-java/
If you're building a web-app your resources should be declared externally, for example in a Tomcat Context.xml file. The password will be located there, not in your code. And keeping that secure is a matter of physical security.
Java code will be executed on the server if you mean a Tomcat web application for example. So it should be ok so.
But if you want to have more security you could create a credentials.properties file, with tomcat as owner and rights of 600. Then you read username and password from that file.
And of course you could encrypt it in the file.
EDIT: And the credentials.properties file should not be accessable over the web ;)
Try Jasypt and it should help:
http://jasypt.org/
Example (Using a .properties file mechanism):
Step1: Find out encrypted password and make a note of it for usage:
StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
String encryptedPassword = passwordEncryptor.encryptPassword(userPassword);
Let's say the encryptedPassword is: G6N718UuyPE5bHyWKyuLQSm02auQPUtm
Step2: Store DB connection credentials in a .properties file with encrypted password
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost/reportsdb
datasource.username=reportsUser
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
Step3: How do we read this value? like this:
/*
* First, create (or ask some other component for) the adequate encryptor for
* decrypting the values in our .properties file.
*/
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("jasypt"); // could be got from web, env variable...
/*
* Create our EncryptableProperties object and load it the usual way.
*/
Properties props = new EncryptableProperties(encryptor);
props.load(new FileInputStream("/path/to/my/configuration.properties"));
/*
* To get a non-encrypted value, we just get it with getProperty...
*/
String datasourceUsername = props.getProperty("datasource.username");
/*
* ...and to get an encrypted value, we do exactly the same. Decryption will
* be transparently performed behind the scenes.
*/
String datasourcePassword = props.getProperty("datasource.password");
// From now on, datasourcePassword equals "reports_passwd"...
For decrypting the encrypted value, we just had to access it with getProperty, just as with any other non-encrypted value.
Details here: http://www.jasypt.org/encrypting-configuration.html
Related
currently I work with Shiro to create an authenticated and authorized connection between server and client.
For now I don't have a special realm and only use the shiro.ini to save all my test users.
My question now is if there is a possibility to save the salt for each user in the shiro.ini or do I have to create a seperate database as a realm?
So is there the chance to save it somehow like this within the .ini?
[users]
*username* = *hashed Password*, *salt*, *roles
I actually do not really understand how or where I can save a random salt for each user.
My current understanding is that the 'hashed Password' in the ini is the final comparison value, for the incoming token containing a password that firstly has to be hashed with the user specific salt.
I have been storing my passwords in plain-text for development purposes but want to start storing the hashes instead, but have so far not yet succeeded in having GlassFish properly authenticate against a hashed password due to the following SecurityException:
SEVERE: jdbcrealm.invaliduserreason
WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
First off, I am running GlassFish 3.1 and have setup the digest for my JDBC realm to SHA-256.
My User class has the following annotated password field:
#Basic(fetch = FetchType.LAZY)
#Column(length = 45, nullable = false)
private String password;
The following helper method is responsible for hashing the password:
private byte[] digest(String input) {
byte[] output = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
output = md.digest(input.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
}
return output;
}
I then set the password on the user as follows:
u.setPassword(Base64.encode(digest(password)).toString());
I wouldn't have Base64 encoded the because this seems to be undocumented but this question: Glassfish Security - jdbcRealm: How to configure login with SHA-256 digest suggests you do need to do so.
So I guess what I would like to know is, does GlassFish expect a String (VARCHAR) or a byte[] (BLOB) as the password field in the database, am I correctly hashing the password, and is it correct to additionally Base64 encode the password hash?
Thanks!
Does GlassFish expect a String (VARCHAR) or a byte[] (BLOB) as the password field in the database?
It expects a column that maps to the Java Type java.lang.String in JDBC, and those would typically be CHAR, VARCHAR etc. LOBs would not work as the JDBC realm implementation issues a ResultSet.getString method call invocation to obtain the password hash.
Am I correctly hashing the password, and is it correct to additionally Base64 encode the password hash?
Base64 encoding is not the only supported option. You can perform Hex encoding as well. But you must perform either of these, and configure the JDBC Realm to perform the same at runtime. In the absence of an encoding parameter, Glassfish will convert the byte sequence associated with the digest, to a sequence of characters in the charset configured for the realm.
I suspect the problem has something to do with the mention of UTF-8 encoding in the expression input.getBytes("UTF-8"). It would be worth verifying if the Base64 encoding of the result provided by your digest method actually matches the password hashes stored in the database.
Also, considering the reason provided for the failure being jdbcrealm.invaliduserreason, I would also suspect that one of the following conditions might be true:
The encoding parameter is not specified for the JDBC Realm; it should preferably be one of base64 or hex (the case does not matter, going by the source code of the JDBC realm), otherwise you would end up in the scenario where the digest byte array is converted to a character array (which in my opinion is a bit flaky unless you can guarantee that the password provided by users are always in a particular encoding).
No password hash exists for the user in the database. See my previous answer on the SQL query executed; you might want to run the query yourself. You can log the statements issued by Derby (if you are using it as the database), by placing a file named derby.properties in the location of your Derby database with the property derby.language.logStatementText=true in it. On shutting down the database, the derby.log file will be populated with all the queries issued by the application server.
The SQL statement prepared by Glassfish is incorrect.
A connection to the database could not be established.
My goal is to authenticate to the database using a JDBC/Hibernate in a secure manner, without storing passwords in plain text. Code examples appreciated. I'm already using waffle to authenticate the user so if there was some way to use the credentials that waffle obtained from the user, and forward those to the DB, that would be good.
Two questions:
What is the recommended way to do multi hop authentication (the client, web server, and database are all different machines) with tomcat/hibernate/spring on web server, a sql database, and obviously client browser?
I would also settle for a way to use a single user account to do authentication, as long as that user account's information was not stored in plain text anywhere. The user account will need both read/write privileges on the DB.
I found some useful information about connecting to SQL Server in this thread. However, I'm expecting that Tomcat will be running under the default account which is like, Local System or something. As far as I know, that account cannot be used to do windows authentication to the database.
My solution:
I did end up using the approach mentioned in the above thread. Instead of running the Tomcat service as Local System it is now running as a user. That user has permission to access the database. My hibernate configuration file is configured as follows:
<property name="hibernate.connection.url">
jdbc:sqlserver://system:port;databaseName=myDb;integratedSecurity=true;
</property>
To those who provided responses
I appreciate everyone's help and I will try out some of the techniques mentioned in the thread. My issue with some of the responses is that they require symmetric encryption which requires a secret key. Keeping the key secret is almost the exact same problem as storing the password in plain text.
i recently blogged about this:
you can tell tomcat's jdbcrealm to use a digest algorithm on the password like sha-256 and save the hash rather than plaintext passwords.
Suppose your User entities look like this:
#Entity
#Table(name = "cr_users")
public class UserDetails{
#Id
#GeneratedValue
private long id;
private String name;
private String passwordHash;
#ManyToMany
private Set<Group> groups;
}
when creating a new User via a service it's possible to create a password hash by using a MessageDigest:
public UserDetails createNewUser(String username,String passwd,Set<Group> groups){
UserDetails u=new UserDetails();
u.setname(username);
u.setGroups(groups);
u.setPassword(createHash(passwd));
return u;
}
public String createHash(String data){
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(password.getBytes());
byte byteData[] = digest.digest();
//convert bytes to hex chars
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
since SHA-256 will always yield the same hashvalue for the same input you can tell tomcat's JDBCRealm to use this algorithm to verify passwords.
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.postgresql.Driver"
connectionURL="jdbc:postgresql://localhost:5432/mydb"
connectionName="myuser" connectionPassword="mypass"
userTable="tc_realm_users" userNameCol="username" userCredCol="passwordhash"
userRoleTable="tc_realm_groups" roleNameCol="groupname"
digest="sha-256"/>
the problem is that tomcat will expect a distinct format for the usertable like this:
+----------------------+ +-------------------+
| tc_realm_users | | tc_realm_groups |
+----------------------+ +-------------------+
| username varchar | | username varchar |
| passwordhash varchar | | groupname varchar |
+----------------------+ +-------------------+
if your user data model fits you're lucky, but my Hibernate generated tables looked like that:
+----------------------+ +-------------------+ +--------------------+
| cr_users | | cr_groups | | cr_users_cr_groups |
+----------------------+ +-------------------+ +--------------------+
| id long | | id long | | cr_users_id long |
| name varchar | | name varchar | | groups_id long |
| passwordhash varchar | +-------------------+ +--------------------+
+----------------------+
so i created a View using SQL which had the expected format and draws it's data from my webapps user data:
create view tc_realm_groups as
select
cr_users.name as username,
groups.name as groupname
from cr_users
left join (
select
cr_users_cr_groups.cr_users_id,cr_groups.name
from cr_groups
left join
cr_users_cr_groups
on cr_users_cr_groups.groups_id=cr_groups.id
) as groups on groups.cr_users_id=id;
create view tc_realm_users as
select
name as username
from cr_users;
with that tomcat was able to authenticate/authorize agains my already existing user data and wrote the data in the context so i could use it in my Jersey (JSR-311) resources:
public Response getEvent(#Context SecurityContext sc,#PathParam("id") long id) {
log.debug("auth: " + sc.getAuthenticationScheme());
log.debug("user: " + sc.getUserPrincipal().getName()); // the username!
log.debug("admin-privileges: " + sc.isUserInRole("webapp-admin"));
return Response.ok(“auth success”).build();
}
there are also some other Realm implementations out there:
JDBCRealm
DataSourceRealm
JNDIRealm
UserDatabaseRealm
MemoryRealm
JAASRealm
CombinedRealm
LockOutRealm
some links:
http://tomcat.apache.org/tomcat-6.0-doc/realm-howto.html
http://www.ericonjava.com/?p=325
http://objecthunter.congrace.de/tinybo/blog/articles/89
If I understand correctly, your environment is hibernate framework based web app deployed in tomcat.
Now currently you must have configured JDBC passsword
i) either in your hibernate configuration file (generally hibernate.cfg.xml file) in property :-
hibernate.connection.password
ii) or in tomcat configuration file:-
<Resource name="jdbc/myoracle" ......password="tiger".../>
Now you wish to NOT store clear password in any of above files.
In your application code, you must be doing :-
Line1: org.hibernate.cfs.Condiguration configuration=new Configraution().configure(<hibernate configuration path>);
then,Line2: configuration.buildSessionFactory().openSession() to create a hibernate session which has underlying JDBC connection.
1) One way can be basically:-
You can have your password encrypted using any java security alogirthm using any JCE provider.You store the encrypted password in any of above configuration files (hibernate or tomcat as per your project environment).
and then between Line1 and Line2, you can have decryption logic like:-
Line1: org.hibernate.cfs.Condiguration configuration=new Configraution().configure(<hibernate configuration path>);
String encrpytedPassword=
configuration.getProperty("hibernate.connection.password"); \\will return encrypted password
//decryption logic to decypt the encrypted password:-
String decryptedPwd=decrypt(encrpytedPassword);
configuration.setProperty("hibernate.connection.password",decryptedPwd);
then,Line2: configuration.buildSessionFactory().openSession()
You can make encryption and decryption as complex as you wish for e.g. encryption of reverse-string-of-clear-password.
You can use any JCE API:- jasrypt,bouncy castle.
You should need some understanding of java cryptography.Please refer to :-
http://download.oracle.com/javase/1.4.2/docs/guide/security/CryptoSpec.html
2)In case you are concerned about password being transmitting in clear in JDBC connection protocol, then you can use SSL support from DB provider to secure connection. For e.g. to have SSL JDBC connection with your DB server. Refer to your DB server resoruces for this.
EDITED TO CLARIFY keylM's comment ON
HOW TO ENCRYPT THE JDBC PASSWORD
lets say you have a private and public key pair:= privare.key and public.cer.
You can have JDBC password encrypted with private key and save the encrypted password in configuration file. You can use OpenSSL to import public certificate into jks (java keystore) file and have it in your JAVA_HOME\jre\lib\security.
In your decryption logic:-
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystore.jks"),<jks password>); //jks password can be hardoded
Certificate cert= ks.getCertificate(<certificate alias>);
//use certificate to decrypt the encrypted password
So in this scenario:-
a hacker would need 3 things in order to capture JDBC password which makes system less vulenrable:-
i) encrypted JDBC password
ii) JKS store
iii) JKS store password
You may ask question of then now how about JKS store password, well whether its a key,passphrase or password, in encryption-decryption system, atleast one thing shuld be highly secure; otherwise it jeopradize the whole system....in above scenario, certificate can be given to each developer machine to let him import into his jks file protected by same jks store password..everybody (developer) would know only JKS store password but never JDBC password...
Normally you'd have the app authenticate to the sql database under just one user name, passing the user's details if necessary as data in its queries so that you return data pertinent to just that end user. Have your clients specified that each end user should authenticate to the database as a separate user?
Okay, let's take a look at the problem. You want to have the authentication information made available but not hardcoded anywhere in code or in file system. What I would suggest:
require the administrator of the application to specify the authentication information upon application startup either via jmx or via a webpage that does not require any database connection.
Add a servlet filter to limit access until database authentication information is entered.
This solution does require some extending spring context loading so that it waits until the authentication information is specified (via entry page).
To be able to transparently encrypt/decrypt passwords in your database with hibernate you need to integrate something like Jasypt.
Homepage: www.jasypt.org
See section: Jasypt + Hibernate 3
Here is how to integrate it:
Download jasypt.jar and add it to your runtime classpath
I would suggest using a registered encryptor:
<typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
<param name="encryptorRegisteredName">strongHibernateStringEncryptor</param>
</typedef>
<class name="User" table="USER">
<property name="password" column="PASSWORD" type="encrypted" />
<class>
Usually, this is handled using a "sysadmin" approach - using the OS:
The basic concept is "externalising configuration parameters".
Passwords are stored in plaintext in a "properties file" (that the web server accesses at runtime). The passwords are protected by restricting access to the files using OS-level file permissions. Typically, only "operations" staff can read/write the file, and the web server needs to run with read-only privileges to the file.
The benefits of this approach are:
Simple to understand and implement (no entering encrypted values)
Protected by software designed to protect - it's one of the few things that an OS does (also, encryption can be cracked if the file can be read)
Simple to set up dev/test environments - just open up permissions for dev/test. Also, only the production runtime server needs to have proper security
Avoids dependencies on "no business value" libraries (that don't help solve your business problem)
You can use a JDNI Datasource on your application server that will have the connection information for the Database.
Then you can just tell your application via your web.xml to use the datasource on your web application server.
Here is how I did it on a Weblogic 9 using Hibernate 3:
In Hibernate.cfg.xml
<property name="connection.datasource">jdbc/MYJDNINAME</property>
<property name="connection.autocommit">true</property>
<property name="hibernate.connection.release_mode">on_close</property>
In weblogic.xml
<reference-descriptor>
<resource-description>
<res-ref-name>jdbc/MYJDNINAME</res-ref-name>
<jndi-name>MYJDNINAME</jndi-name>
</resource-description>
</reference-descriptor>
Similar solutions can be used for tomcat and other application servers:
Tomcat 6 Instructions
I got your point KyleM. You can do :
Create plain text file or registry(in case of Windows) place somewhere on other server in encrypted mode.
OR you can use this Lamport's one-time password algorithm
Users log in to my BlackBerry app with a username and password provided at registration. My app connects to a Java Web Service that does all the logic.
How do I go about storing the password and username in a safe manner on my server? Everybody says salting and hashing, but I have no idea how to do this since I've never worked with it. How can I do this in Java?
How do I manage sending the password securely from the app to the server?
To store the credentials, one possibility is to use PBKDF2. A Java implementation (that I have not used) is available here. Run the password with the salt value through that and store the resulting hash data. The salt value is typically a newly generated random value (one for each password). This helps prevent dictionary attacks via rainbow tables (pre-computed tables of hashed passwords). Using java.security.SecureRandom is a possibility for generating those.
The client application should probably connect to the server using SSL/TLS. That will provide the encryption to protect the credentials when passed from client to your server application.
Edit Based on our conversation in the comments, it sounds as if the goal is not to use SSL. Assuming that is true and no other end-to-end communications encryption is planned, then it seems to imply that the security of the communications is not a high priority. If that is true, then maybe the described scheme for authenticating is sufficient for the application. Nonetheless, it seems worth pointing out the potential issues so you can consider them.
The proposed scheme (I think) is to send from the client to the server this value: Hash(Hash(password,origsalt),randomsalt). What this really means is that the password is effectively Hash(password,origsalt). If the attacker can get that information, then they can login as that user because they take that value and hash it with the new salt value to authenticate. In other words, if the database of hashed passwords is compromised, then the attacker can easily gain access. That somewhat defeats the purpose of salting and hashing the passwords in the first place.
Without SSL (or some other end-to-end encryption), there is the possibility of a man-in-the-middle attack. They can either listen in or even impersonate one end of the conversation.
Seems like your question has a few parts...
The most secure way to store the password in the database is to use a hash with a Salt + Pepper seed as described here. If you want to find a good way of implementing that specific technique in Java, try opening a new question.
I can see why it would make sense to encrypt a username/password hash prior to sending to the server, since SSL proxies can be a man-in-the-middle for that operation.
As a solution try creating a token in JSON or XML format that has the following properties:
Username.ToUpper() // Dont want this to be case sensitive
ExpiryDate (Say now plus 5 minutes)
Nonce (a random number that is saved on the backend to prevent replay attacks)
SHA 256 signature
Use the locally entered username and password to create a SHA256 signature, as it will be a constant. Use this signature to sign the JSON or XML you send to the server with each request.
In other words you're using a symmetric key based on the username and password, without sending it across the wire. Of course you may want to salt and pepper the generation of that symmetric key for more security.
That's all I got for a high level design, since I'm not intimately familiar with Java. Do share your links/code when you do find the answers.
So here's what I ended up doing:
package Utils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
/**
*
* #author octavius
*/
public class SalterHasher {
private String salt;
private String pepper = "******************";
private String hash;
private String password;
public SalterHasher(String password, String username)
{
this.password = password;
salt = RandomStringUtils.random(40, username);
hash = DigestUtils.md5Hex(password + salt + pepper);
}
public String getHash(){
return hash;
}
/**
* #return the salt
*/
public String getSalt() {
return salt;
}
public String makeHash(String salt){
return DigestUtils.md5Hex(password + salt + pepper);
}
}
A very simple class that generates a salt and the hash for me and has a pepper included for added security, the makeHash() function I use for verification when the user logs in. In view of what I previously mentioned in the comments above I didn't end up using the verification process I proposed and chose to simply add the pepper to my server side code since hashing I believe would prove to be heavy on the BlackBerry device. Thanks again to those who helped me. Good discussions were had :)
I am using the JConsole to access my application MBeans and i use the the password.properties file. But as per the Sun's specification this file contains passwords in clear text formats only.
com.sun.management.jmxremote.password.file=<someLocation>/password.properties
Now i would want to encrypt the password and use it for the JMX user authentication from JConsole (the username and password fields in Remote section). I could use any pre-defined encryption logic or my own encryption algorithms.
Does anyone know of any such interception to change the plain text password to encrypted one so that the JMX Framework too knows about the encrypted password?
My Current password file:
guest guest
admin admin
With Encryption it should look like:
guest ENC(RjqpRYbAOwbAfAEDBdHJ7Q4l/GO5IoJidZctNT5oG64=)
admin ENC(psg3EnDei6fVRuqHeLwOqNTgIWkwQTjI2+u2O7MXXWc=)
You can use the configuration parameter com.sun.management.jmxremote.login.config in the management.properties file (see %JAVA_HOME%/lib/management/management.properties) to configure which Authenticator and LoginModule to use.
The default is the following:
JMXPluggableAuthenticator {
com.sun.jmx.remote.security.FileLoginModule required;
};
which reads plain text password file jmxremote.password. Since the com.sun.jmx.remote.security.JMXPluggableAuthenticator can be reconfigured
to use any LoginModule implementation, you are free to either choose an existing LoginModule or to implement your own
which uses encrypted password files.
To reimplement FileLoginModule, you should have a look at the attemptAuthentication(boolean) method, which
actually performs the authentication and which you probably are going to replace. Implement the javax.security.auth.spi.LoginModule interface
and use the given CallbackHandler (you will get it from the init() method) to ask for a username and password. Encrypt/hash the received password and compare it against the one read from your encrypted password file. Pseudo code:
public class EncryptedFileLoginModule implements LoginModule {
#Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
attemptLogin();
if (username == null || password == null) {
throw new LoginException("Either no username or no password specified");
}
MessageDigest instance = MessageDigest.getInstance("SHA-1");
byte[] raw = new String(password).getBytes();
byte[] crypted = instance.digest(raw);
// TODO: Compare to the one stored locally
if (!authenticated) throw new LoginException();
return true;
}
private void attemptLogin() throws LoginException {
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("username");
callbacks[1] = new PasswordCallback("password", false);
callbackHandler.handle(callbacks);
username = ((NameCallback) callbacks[0]).getName();
user = new JMXPrincipal(username);
char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
((PasswordCallback) callbacks[1]).clearPassword();
}
However, as this is already the server-side, the password would afaik be still transferred in plain text if you don't enforce
JMX over SSL. So, either enforce SSL or use another transport protocol mechanism which encodes the credentials before
transmitting them over the wire.
To conclude, it's perhaps much better to rely on existing authentication mechanisms provided by JAAS. If, for example,
you're running in a local Windows environment, you can easily use the NTLoginModule for auto-login. But it only works on local machine.
Create a file c:/temp/mysecurity.cfg:
MyLoginModule {
com.sun.security.auth.module.NTLoginModule REQUIRED debug=true debugNative=true;
};
Next, configure the jmxremote.access file to contain the usernames or roles you wish to grant access to your JMX server:
monitorRole readonly
controlRole readwrite ...
mhaller readonly
(I recommend to enable debug mode until it works. You will see all the user names, domain names and group names when a user tries to log in)
Set the following JVM arguments for your server:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8686
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=true
-Djava.net.preferIPv4Stack=true
-Djava.security.auth.login.config=c:/temp/mysecurity.cfg
-Dcom.sun.management.jmxremote.login.config=MyLoginModule
Start up your application and try to connect using JConsole or VisualVM.
Note that JConsole, you will need to specify a username and a password, although it's not going to be used. Any password and any username will work.
The reason is because jconsole will try to authenticate with null username and null password, which is blocked explicitly.
VisualVM does a better job by using empty strings for username and password when none are entered by the user.
Also note that the NTLoginModule does not work when connecting remotely, i think you would have to use a more sophisticated login module,
but Sun already provides enough of them:
com.sun.security.auth.module.Krb5LoginModule: Authenticates users using the Kerberos protocols
com.sun.security.auth.module.LdapLoginModule: (new in Java 6): Performs authentication against an LDAP server by specifying technical connection user
com.sun.security.auth.module.JndiLoginModule: Performs authentication against an LDAP server registered in the JNDI context
com.sun.security.auth.module.KeyStoreLoginModule: Authenticates users by using a Java Keystore. Supports PIN or smart card authentication.
You will want to have a look at the LdapLoginModule