1

我有密码哈希的问题。我想用盐和 1024 次迭代应用 sha-256 来使用 Spring Security 对我的用户进行身份验证。但不知何故,我在数据库中的密码与用户输入的密码不匹配。

这是我的代码:

安全上下文.xml

<beans:bean
    id="passwordEncoder"
    class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" >
    <beans:constructor-arg value="256" />
    <beans:property
        name="iterations"
        value="1024" />
</beans:bean>

<beans:bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
    <beans:property name="userPropertyToUse" value="id"/>
</beans:bean>

<authentication-manager>
    <authentication-provider user-service-ref="userLoginDetails" >
        <password-encoder ref="passwordEncoder" >
             <salt-source ref="saltSource"/>
        </password-encoder>
    </authentication-provider>
</authentication-manager>

用户登录详情

@Transactional(readOnly = true)
public class UserLoginDetails implements UserDetailsService {

private EregDaoFactory daoFactory;

@Autowired
public void setDaoFactory(EregDaoFactory daoFactory) {
    this.daoFactory = daoFactory;
}

/**
 * Retrieves a user record containing the user's credentials and access.
 */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,
        DataAccessException {
    Logger logger = Logger.getLogger(getClass());
    logger.setLevel(Level.ALL);

    int userId = Integer.parseInt(username);

    UzytkownikDao dao = daoFactory.getUzytkownikDao();

    LoggedUser user = null;
    Uzytkownik dbUser = null;

    try {

        dbUser = (Uzytkownik) dao.findById(Integer.parseInt(username));
        List<SimpleGrantedAuthority> grants = new ArrayList<SimpleGrantedAuthority>();
        Collection<Object> userNames = new ArrayList<Object>();

        if (dbUser.getRola() == 'U') {
            grants.add(new SimpleGrantedAuthority("ROLE_STUDENT"));
            userNames = daoFactory.getUczenDao().getNameAndLastName(userId);

        } else if (dbUser.getRola() == 'N') {
            grants.add(new SimpleGrantedAuthority("ROLE_TEACHER"));
            userNames = daoFactory.getNauczycielDao().getNameAndLastName(userId);
        } else if (dbUser.getRola() == 'O') {
            grants.add(new SimpleGrantedAuthority("ROLE_PARENT"));
            userNames = daoFactory.getOpiekunDao().getNameAndLastName(userId);
        }
        grants.add(new SimpleGrantedAuthority("ROLE_USER"));

        Object[] names = userNames.toArray();
        user =
                new LoggedUser(username, dbUser.getHaslo(), true, true, true, true, grants,
                        (String) names[0], (String) names[1], dbUser.getRola());
    } catch (Exception e) {
        logger.error(e.getLocalizedMessage());
        throw new UsernameNotFoundException("Error in retrieving user");

    }

    return user;

}

}

登录用户

    package ereg.security.userdetails;

public class LoggedUser extends User {

private static final long serialVersionUID = 1L;
private final String id;
private final String imie;
private final String nazwisko;
private final char rola;
private Date lastSuccessfulLogin;
private String lastKnowIpAddress;

public LoggedUser(String username, String password, boolean enabled, boolean accountNonExpired,
        boolean credentialsNonExpired, boolean accountNonLocked,
        Collection<? extends GrantedAuthority> authorities, String name, String lastName, char rola) {
    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
            authorities);
    this.imie = name;
    this.nazwisko = lastName;
    this.rola = rola;
    this.id = username;
}

public String getId() {
    return id;
}

public String getImie() {
    return imie;
}

public String getNazwisko() {
    return nazwisko;
}

public char getRola() {
    return rola;
}

public Date getLastSuccessfulLogin() {
    return lastSuccessfulLogin;
}

public String getFormattedDate() {
    if (lastSuccessfulLogin != null) {
        return new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(lastSuccessfulLogin);
    } else
        return null;
}

public String getLastKnowIpAddress() {
    return lastKnowIpAddress;
}

public void setLastSuccessfulLogin(Date lastSuccessfulLogin) {
    this.lastSuccessfulLogin = lastSuccessfulLogin;
}

public void setLastKnowIpAddress(String lastKnowIpAddress) {
    this.lastKnowIpAddress = lastKnowIpAddress;
}

}

这是哈希密码的程序:

加密所有用户密码

private void encryptPasswords() throws Exception {
    OneWayEncryptor encryptor = OneWayEncryptor.getInstance();

    appContext =
            new FileSystemXmlApplicationContext(
                    "C:/EclipseWorkSpace/myereg/WebContent/WEB-INF/applicationContext.xml");

    ds = (DataSource) appContext.getBean("dataSource");
    JdbcTemplate jdbc = new JdbcTemplate(ds);
    BigDecimal userId = null;
    String password = "";
    String encrypted = "";

    Map<?, ?> row = new HashMap<Object, Object>();

    for (Iterator<?> it = jdbc.queryForList("SELECT id, haslo FROM UZYTKOWNIK").iterator(); it.hasNext();) {
        row = (Map<?, ?>) it.next();

        userId = (BigDecimal) row.get("ID");
        password = (String) row.get("HASLO");
        encrypted = encryptor.encrypt(password, userId.toString());

        System.out.println(userId.toString());

        jdbc.execute("UPDATE UZYTKOWNIK SET haslo = '" + encrypted + "'  WHERE id = " + userId);

    }
}

public static void main(String[] args) {

    EncryptAllUserPasswords encrypt = new EncryptAllUserPasswords();
    try {
        encrypt.encryptPasswords();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

单向加密器

public final class OneWayEncryptor {
private static final OneWayEncryptor INSTANCE = new OneWayEncryptor();

private static final int ITERATIONS = 1024;
private static final String ALGORITHM = "SHA-256";

private OneWayEncryptor() {
}

public static OneWayEncryptor getInstance() {
    return INSTANCE;

}

public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
        UnsupportedEncodingException {
    MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);

    messageDigest.reset();
    messageDigest.update(salt.getBytes());

    byte[] btPass = messageDigest.digest(plaintext.getBytes("UTF-8"));
    for (int i = 0; i < ITERATIONS; i++) {
        messageDigest.reset();
        btPass = messageDigest.digest(btPass);
    }

    String encodedPassword = byteToBase64(btPass);

    return encodedPassword;
}

private String byteToBase64(byte[] bt) throws UnsupportedEncodingException {

    return new String(Base64.encodeBase64(bt));

}

}

我相信问题出在最后一个...请帮助

4

1 回答 1

2

实际上,这有效:

public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
        UnsupportedEncodingException {
    String pass = plaintext + "{" + salt + "}";
    MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);

    messageDigest.reset();
    byte[] btPass = messageDigest.digest(pass.getBytes("UTF-8"));

    for (int i = 0; i < ITERATIONS - 1; i++) {
        messageDigest.reset();
        btPass = messageDigest.digest(btPass);
    }

    String hashedPass = new BigInteger(1, btPass).toString(16);
    if (hashedPass.length() < 32) {
        hashedPass = "0" + hashedPass;
    }

    return hashedPass;
}

有人可以告诉我为什么吗?我的意思是为什么当我尝试使用 update(salt) 方法时它会做,而当我切换到连接字符串时它会做。而且我不介意使用“{salt}”,因为这只允许我生成与 spring 完全相同的哈希。问题是,即使给定盐,它也会在生成错误哈希之前。我用 sha256 生成器检查了它。有人能告诉我为什么它在字符串连接后开始工作吗?

于 2012-05-30T22:05:04.883 回答