【发布时间】:2011-12-01 07:29:18
【问题描述】:
那里有教程吗,或者有人有关于如何使用 Spring-Security 执行以下操作的指示吗?
任务:
我需要从我的数据库中获取用于验证用户名的 salt,并使用它来加密提供的密码(来自登录页面),以将其与存储的加密密码(也就是验证用户)进行比较。
其他信息:
我使用自定义数据库结构。 UserDetails 对象是通过自定义 UserDetailsService 创建的,而 UserDetailsService 又使用自定义 DAOProvider 从数据库中获取信息。
到目前为止我的security.xml 文件:
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
</authentication-provider>
</authentication-manager>
现在我想我需要
<password-encoder hash="sha" />
但还有什么?如何告诉 Spring Security 使用数据库提供的盐来编码密码?
编辑:
我发现This SO 的帖子提供了丰富的信息,但还不够:如果我在我的 xml 中定义一个盐源以供密码编码器使用,如下所示:
<password-encoder ref="passwordEncoder">
<salt-source ref="saltSource"/>
</password-encoder>
我必须编写一个自定义 SaltSource 才能使用我的自定义盐。但这在UserDetails 对象中找不到。所以...
备选方案 1:
我可以使用自定义的 UserDetails 实现,它可能具有 salt 属性吗?
<beans:bean id="saltSource" class="path.to.MySaltSource"
p:userPropertyToUse="salt"/>
和
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
// ...
return buildUserFromAccount(account);
}
@Transactional(readOnly = true)
UserDetailsImpl buildUserFromAccount(Account account){
// ... build User object that contains salt property
}
自定义用户类:
public class UserDetailsImpl extends User{
// ...
private String salt;
public String getSalt() { return salt; }
public void setSalt(String salt) { this.salt = salt; }
}
security.xml:
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder hash="sha">
<salt-source ref="saltSource"/>
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="salt"/>
备选方案 2:
否则我必须将我的 accountDAO 注入 SaltSource 以从数据库中提取给定 userName 的盐。
但是:Spring Security 如何调用SaltSource?始终使用saltSource.getSalt(userDetails)?
然后我只需要确保我的SaltSource 在我的accountDAO 上使用userDetails.accountName 来检索盐。
编辑2:
刚刚得知我的方法是.. legacy.. :( 所以我想我会使用StandardPasswordEncoder(我仍然需要弄清楚如何使用它)。
顺便说一句:我使用扩展 User 类的自定义 UserDetails 类实现了第一个选项,并且只添加了一个 salt 属性,然后将其作为 userPropertyToUse 传递给 SaltSource,就像在编辑 1 中提到的 SO 帖子中提出的那样...
编辑 3:
StandardPasswordEncoder 刚刚开始工作,所以我将在此处留下一些提示:
使用 StandardPasswordEncoder 进行身份验证:
<beans:bean id="encoder"
class="org.springframework.security.crypto.password.StandardPasswordEncoder">
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="encoder" />
</authentication-provider>
</authentication-manager>
这需要3.1.0.RC版本的spring-security-crypto模块?据我所知。找不到任何具有 3.0 的存储库。版本(即使某处列出的版本包括 3.0.6 等)。此外,文档还谈到了 spring security 3.1,所以我想,我会继续这样做。
创建用户时(对我来说只有管理员可以这样做),我只使用
StandardPasswordEncoder encoder = new StandardPasswordEncoder();
String result = encoder.encode(password);
我已经完成了。
Spring security 会随机创建一个 salt 并将其添加到密码字符串中,然后再将其存储到数据库中,因此 不再需要 salt 列。
然而,也可以提供一个全局盐作为构造函数参数 (new StandardPasswordEncoder("12345");),但我不知道如何设置我的安全配置以从 bean 中检索该值,而不是使用 @987654344 提供静态字符串@。不过我也不知道到底需要多少。
【问题讨论】:
标签: authentication passwords spring-security salt