1

need some help or direction using Spring's security 3.1.x.

I am storing an encrypted password in MySql database. Which password is defined as a varchar(60) column.

The first time running the web app, I generated the password with the following code snippet:

String p = "12345";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(p);

I then took the String encodedPassword and pasted into the database column. I kept the code in my authentication-manager (snippet follows), and logged encodedPassword to the server log.

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider user-service-ref="usersDAO"> 
        <security:password-encoder ref="encoder" />
    </security:authentication-provider>
</security:authentication-manager>

<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

My problem is that authentication fails with exception: Bad credentials when BCryptPasswordEncoder.matches() runs. The stored password is not matching the generated hash from the form input. The same text password that was used in the initial hash generation was used.

Each time I re-run the login entering the same text, the logged encodedPassword is different. Debugging I can see where the entity is being returned from the database correctly, so I don't think that is an issue. The issue seems to me that I'm not doing/setting something correctly in order to generate the same hash each time the text password is entered.

EDIT: Adding usersDAO.

import org.springframework.security.core.userdetails.UserDetailsService;

public interface UsersDAO extends Dao<Users>, UserDetailsService 
{
    Users getByUsername(String username);   
}

EDIT: adding implementation.

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Repository("usersDAO")
public class UsersDAO_DB extends AbstractHibernateDao<Users> implements UsersDAO
{
final Logger log = LoggerFactory.getLogger(this.getClass());

@Override
public Users getByUsername(String username) 
{
    String p = "12345";
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String encodedPassword = passwordEncoder.encode(p);
    log.debug("HELLOZ  ---->  " + encodedPassword);

    notNull(username, "username can't be null");
    return (Users) getSession()
        .getNamedQuery("users.byUsername")
        .setParameter("username", username)
        .uniqueResult();
}

@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws     UsernameNotFoundException, DataAccessException {
    notNull(username, "username can't be null");
    Users users = getByUsername(username);
    if (users == null) {
        throw new UsernameNotFoundException("No user with username " +  username);
    }
    return users;
}


@Override
public void create(Users t)
{
    // TODO Auto-generated method stub
}

@Override
public void update(Users t)
{
    // TODO Auto-generated method stub

}

@Override
public void delete(Users t)
{
    // TODO Auto-generated method stub

}

}

Any ideas?

2 Answers 2

2

This was a newbie error here following a couple of different tutorials.

In the bean I had defined my security encoder as a: org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

To generate a test cryptic password I used the following code:

String p = "12345";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(p);
log.debug("HELLOZ  ---->  " + encodedPassword);

which was mixing the org.springframework.security.crypto.password.PasswordEncoder and the org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. See the above code defining passwordEncoder.

Once I changed it to:

String p = "12345";
BCryptPasswordEncoder pe= new BCryptPasswordEncoder();
String encPassword =pe.encode(p);
log.debug("HELLB  ---->  " + encPassword);

copied the output to my database and retested everything worked fine.

Sign up to request clarification or add additional context in comments.

Comments

1

Each time I re-run the login entering the same text, the logged encodedPassword is different".

Where is that logging coming from? Spring Security won't log incoming passwords and if you are using BCrypt it shouldn't be re-encoding them from scratch anywhere.

It sounds like you may be re-encoding the submitted password yourself, possibly in your usersDAO which isn't shown.

If not, please post your complete configuration and the logging output you're talking about.

3 Comments

No I'm not doing anything with the plain text password entered, but generating a hash that is used to print a debugging statement. Also that's what I was talking about when I said logging the password.
The hashes will always be different since BCrypt uses a different salt each time, so that doesn't mean anything. I'd still guess that something is going on in your own DAO. The interface you've posted doesn't have any code so unless you post the actual implementation it's hard to say.
Sorry I didn't know exactly what you needed. If you need more just let me know. I gathered that the salt was causing the unmatched passwords, but that was all I was able to gather.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.