Spring安全密码验证

时间:2013-10-24 16:45:57

标签: authentication spring-security

使用Spring的安全性3.1.x需要一些帮助或指导。

我在MySql数据库中存储加密密码。哪个密码定义为varchar(60)列。

首次运行网络应用时,我使用以下代码段生成了密码:

String p = "12345";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(p);
然后我接受String encodedPassword并粘贴到数据库列中。我将代码保存在我的身份验证管理器中(后面的代码段),并将encodedPassword记录到服务器日志中。

<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" />

我的问题是身份验证失败并出现异常:BCryptPasswordEncoder.matches()运行时凭据错误。存储的密码与表单输入中生成的哈希不匹配。使用了在初始哈希生成中使用的相同文本密码。

每次重新运行登录时输入相同的文本,记录的encodedPassword都不同。调试我可以看到正确地从数据库返回实体的位置,所以我不认为这是一个问题。在我看来,问题是我没有正确地设置/设置某些东西,以便每次文本生成相同的哈希 输入密码。

编辑: 添加用户DAO。

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

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

编辑: 添加实现。

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

}

}

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

这是一个新手错误,在几个不同的教程之后。

在bean中我将安全编码器定义为: org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

为了生成测试隐秘密码,我使用了以下代码:

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

混合了org.springframework.security.crypto.password.PasswordEncoder和org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder。请参阅上面的代码定义passwordEncoder。

我将其更改为:

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

将输出复制到我的数据库并重新测试一切正常。

答案 1 :(得分:1)

  

每当我重新运行登录时输入相同的文本,记录的encodedPassword就会有所不同“。

记录来自何处? Spring Security不会记录传入的密码,如果你使用BCrypt,它不应该从头开始重新编码它们。

听起来您可能会自行重新编码提交的密码,可能在未显示的usersDAO中。

如果没有,请发布您正在谈论的完整配置和日志输出。