Search code examples
javaauthenticationshiro

Using Shiro's PasswordMatcher with a custom realm


I'm using Apache Shiro with a custom JDBC realm to retrieve a user’s salt, password, hash algorithm name and number of hash iterations from the database which are all stored as separate columns.

The problem is I'm unsure how I should handle the salt that has been retrieved from the database when using the PasswordMatcher to verify the user's password matches that stored in the database.

When using the HashedCredentialsMatcher the salt is set using the setCredentialsSalt method, however it seems that this isn't the case when using the PasswordMatcher instead of the HashedCredentialsMatcher.

The code I'm using in the custom JDBC realm is as follows

@Override 
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 

        //code to retrieve user details from database removed for brevity 

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, passwdSalt.password, getName()); 
        info.setCredentialsSalt(new SimpleByteSource(passwdSalt.salt)); 

        DefaultPasswordService passwordService = new DefaultPasswordService(); 
        DefaultHashService hashService = new DefaultHashService(); 
        PasswordMatcher passwordMatcher = new PasswordMatcher(); 

        hashService.setHashAlgorithmName(passwdSalt.hashAlgorithmName); 
        hashService.setHashIterations(passwdSalt.hashIterations); 
        passwordService.setHashService(hashService); 
        passwordMatcher.setPasswordService(passwordService); 
        setCredentialsMatcher(passwordMatcher); 

        return info; 
} 

Having stepped through the code I've confirmed that the problem is definitely due to the salt not being used when hashing the password entered by the user in order to match it against the hashed password in the database. In DefaultPasswordService.java when the method passwordsMatch(Object submittedPlaintext, String saved) is called on line 160 the object named request contains the following

algorithmName=null 
iterations=0 
salt=null 
source=cGFzc3dvcmQ= 

The next line of code on line 161 calls computeHash(request)

In DefaultHashService.java when the method computeHash(HashRequest request) is called, on lines 155 and 157 the variables algorithmName and iterations are correctly set to SHA-256 and 1 respectively. On line 159 the method getPublicSalt(request) is called however it retuns null.

Has anyone else used Shiro's PasswordMatcher with a custom realm and if how do you tell Shiro to use the salt?


Solution

  • I posted a message on the Shiro mailing list and got a reply saying that the PasswordMatcher by default does not look at anything in the AuthenticationInfo other than authenticationInfo.getCredentials().

    For further details, the archived message on the mailing list is available at http://shiro-user.582556.n2.nabble.com/Migrating-from-HashedCredentialMatcher-to-PasswordMatcher-td7577808.html