This is the second time I'm using apache shiro in a project but the first time am salting the password.this time around i use apache shiro 1.2.0 . I'm using shiro in a web application using jsp, spring, JPA(spring-data-jpa) and using SHA256 for encryption then base64 before saving to database. I have a SaltedJPARealm, a Sha256CredentialMatcher which implements a HashedCredentialMatcher. this is how i do
creating a user in my controller
RandomNumberGenerator rng = new SecureRandomNumberGenerator();
ByteSource salt = rng.nextBytes(10);
String hashedPasswordBase64 = new Sha256Hash(signupForm.getPassword(),salt).toBase64();
userService.createUser(signupForm.getFullName(), signupForm.getEmail(), hashedPasswordBase64, salt.toBase64());
so supposed my password is password1234 and the generated salt is /ZFfGOcSxYhy+g== so in my database i have password: whb+0AihIGJ4n8QwULj1tR6qSwCrA+1BUvnoe4q4Cy4= the salt in the salt field in the database is the same.
In my configuration in spring is:
<!--....-->
<bean id="saltedJPARealm" class="bla.bla.webapp.security.SaltedJPARealm">
<constructor-arg ref="credMatcher"/>
</bean>
<bean id="credMatcher" class="bla.bla.webapp.security.Sha256CredentialMatcher">
<property name="storedCredentialsHexEncoded" value="false" />
<property name="hashAlgorithmName" value="SHA-256" />
<!--<property name="hashIterations" value="1024" />-->
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="userRepository">
<property name="realm" ref="saltedJPARealm" />
</bean>
<!--....-->
login user
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(loginForm.getEmail(), loginForm.getPassword(), loginForm.isRememberMe());
SecurityUtils.getSubject().login(token);
}
The SaltedJPARealm's doGetAuthenticationInfo(AuthenticationToken at) returns SaltedAuthenticationInfo after getting the user from the database :
ByteSource salt = ByteSource.Util.bytes(user.getSalt());
return new SimpleAuthenticationInfo(user, user.getPassword().toCharArray(),salt,this.getName());
the doCredentialsMatch of Sha256CredentialMatcher looks like :
Object tokenfromSubmition = hashProvidedCredentials(token.getCredentials(),((SaltedAuthenticationInfo)info).getCredentialsSalt(),0);
Object passwordFromStorage =this.getCredentials(info);
Boolean match = equals(tokenfromSubmition, passwordFromStorage);
return match;
full code is available here on pastie the authentication fails with this. but when i change the code not to salt the password(when creating account) and return AuthenticationInfo as opposed to SaltedAuthenticationInfo. it works with the same class. am wondering what exactly am doing wrong?
The
PasswordServiceis a POJO (with nested properties) and its nested properties can be configured just as well with Spring:This allows the
myRealminstance to use the PasswordService for credentials checking during a login attempt.To use the PasswordService to encrypt passwords when the end user sets their password (i.e. during account registration or password reset), you can inject the
PasswordServicebean and then use it:I think you'll find the Spring config and code usage much nicer/cleaner to use than the lower-level random number generators and HashService + Hash APIs.
HTH!