是否有教程或者有人指导如何使用 Spring-Security 执行以下操作?
任务:
我需要从数据库中获取用于身份验证用户名的盐,并使用它来加密提供的密码(从登录页面),以将其与存储的加密密码进行比较(也称为对用户进行身份验证)。
其他信息:
我使用自定义数据库结构。 UserDetails
对象是通过自定义 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; }
}
安全.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 注入(inject) SaltSource
才能从数据库中提取给定 userName
的盐。
但是:Spring Security 如何调用 SaltSource
?总是带有 saltSource.getSalt(userDetails)
?
然后我只需要确保我的 SaltSource
在我的 userDetails.accountName
上使用 accountDAO
来检索盐。
编辑2:
刚刚了解到我的方法是..遗留的..:(所以我想我只会使用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 将随机创建一个盐并将其添加到密码字符串中,然后将其存储在数据库中,因此不再需要盐列。
但是,也可以提供全局盐作为构造函数参数( new StandardPasswordEncoder("12345");
),但我不知道如何设置安全配置以从 bean 检索该值,而不是提供带有 <constructor-arg name="secret" value "12345" />
的静态字符串。但我不知道到底需要多少。
请您参考如下方法:
我会将其标记为已回答,因为我解决了我的问题并且没有给出其他评论或答案:
编辑 1 - 替代方案 1 回答原始问题
但是我必须了解到,自定义密码加盐是一种传统方法,Spring Security 3.1 中不再需要这种方法,正如我在
中所描述的那样编辑 3,我在其中留下了一些关于如何使用 StandardPasswordEncoder
来实现与密码一起存储的自动 Salt 的提示。