Spring Security Salt

23

我想在添加新用户/密码时加入盐,但文档似乎没有说明如何操作。

下面是一个基本示例:

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="md5">
            <salt-source user-property="username"/>
        </password-encoder>
    </authentication-provider>
</authentication-manager>

你可以通过这个示例看到,没有使用自定义的盐或密码编码器。
那么,在添加新用户/密码时,我该如何加入盐呢? 我认为应该是以下内容:
@Autowired SaltSource saltSource;
protected void foo(final CustomUser user) {
    final PasswordEncoder encoder = new Md5PasswordEncoder();
    user.setPassword(encoder.encodePassword(user.getPassword(), saltSource));
}

然而,由于我在使用默认的盐/密码编码器并且没有自定义盐bean,因此自动装配会失败。

有什么提示可以让这个工作吗?

1个回答

34

在添加用户时,您没有自动装配 SaltSourceSaltSource 是 Spring 使用的抽象,仅用于提供密码检查的salt源。

要创建正确编码的密码哈希值,只需将 salt 本身传递给 PasswordEncoder - 即 username 属性的值,而不是 SaltSource 的值:

private PasswordEncoder encoder = new Md5PasswordEncoder();

public User createUser(String username, String plainTextPassword) {
    User u = new User();
    u.setUsername(username);
    u.setPassword(encoder.encodePassword(plainTextPassword, username));
    getEntityManager().persist(u); // optional
    return u;
}
此外,只有在将 SaltSource 定义为内部 bean 后,才能自动装配它。你可以将 ReflectionSaltSource 定义为顶级 bean,并将其 ID 传递给 password-encoder。例如:
<bean id="saltSource"
    class="org.springframework.security.authentication.dao.ReflectionSaltSource"
    p:userPropertyToUse="username" />

<bean id="passwordEncoder" 
    class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />

<bean id="daoAuthenticationProvider"
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
    p:passwordEncoder-ref="passwordEncoder"
    p:saltSource-ref="saltSource"
    p:userDetailsService-ref="userDetailsService" />

<authentication-manager>
    <authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>

然后:

@Autowired private PasswordEncoder passwordEncoder;
@Autowired private SaltSource saltSource;

public CustomUserDetails createUser(String username, String plainTextPassword) {
    CustomUserDetails u = new CustomUserDetails();
    u.setUsername(username);
    u.setPassword(passwordEncoder.encodePassword(
            plainTextPassword, saltSource.getSalt(u)));
    getEntityNamager().persist(u); // optional
    return u;
} 

新的代码似乎无法正常工作。我得到了以下错误信息:IllegalStateException: 无法将类型为[java.lang.String]的值转换为所需类型[org.springframework.security.authentication.encoding.PasswordEncoder]以设置属性'passwordEncoder':找不到匹配的编辑器或转换策略。 - user973479
我纠正了XML代码——忘记在引用上加上“-ref”后缀。 - Roadrunner
7
在考虑使用用户名作为盐值来源时需要小心。如果用户名更改,盐值也会更改,因为已编码的密码是基于先前用作盐值的用户名生成的,用户将无法登录。 - th3morg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接