authentication - Spring Security 自定义身份验证和密码编码

标签 authentication passwords spring-security salt

是否有教程或者有人指导如何使用 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 的提示。

关于authentication - Spring Security 自定义身份验证和密码编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7658853/

相关文章:

grails - 外部化 Grails 3 Spring 安全配置

c# - 允许匿名访问 IIS 站点中使用 Windows 身份验证的目录

c# - 在不需要的 OIDC 授权上禁用 Blazor "Authorizing"启动画面

rest - 将 API key 放在 header 或 URL 中

security - bcrypt 对大型网站可行吗?

一组规则的正则表达式密码验证

javascript - 如何在登录后显示某些按钮和余额

javascript - 如何读取未提交给 git 的配置文件

java - Hibernate-Spring Security-Spring MVC版本

unit-testing - 如何模拟从 Controller 测试类注入(inject)域类的服务?