Spring Security 自定义 UserDetails :盐问题

Posted

技术标签:

【中文标题】Spring Security 自定义 UserDetails :盐问题【英文标题】:Spring Security custom UserDetails : salt issue 【发布时间】:2016-09-14 17:12:51 【问题描述】:

我正在尝试在我的网络应用程序中制作身份验证表单。使用自定义 UserDetailsS​​ervice + UserDetails。

它几乎可以工作。当我尝试使用硬编码在我的数据库中的用户和密码登录时,它可以工作。但是当我尝试使用具有加密(Bcrypt)密码的用户登录时它不起作用......

我确定了有问题的代码部分(它是 Spring 提供的一个类):

public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider 

    // [...]

    @SuppressWarnings("deprecation")
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException 
        Object salt = null;

        /* ISSUE : saltSource is null */
        if (this.saltSource != null) 
            /* ISSUE : Moreover, my class UserDetailsImpl which implement UserDetails has no salt attribute */
            salt = this.saltSource.getSalt(userDetails);
        

        if (authentication.getCredentials() == null) 
            logger.debug("Authentication failed: no credentials provided");

            throw new BadCredentialsException(messages.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        

        String presentedPassword = authentication.getCredentials().toString();

        /* ISSUE : Has salt is null, authentication with crypted password doesn't work */
        if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
                presentedPassword, salt)) 
            logger.debug("Authentication failed: password does not match stored value");

            throw new BadCredentialsException(messages.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        
    

    // [...]

此代码中没有盐。因此,当 salt 为空时,它会将加密的数据库密码与硬编码的浏览器密码进行比较:/.

你有什么想法吗?谢谢。

【问题讨论】:

我有同样的问题,isPasswordValid(hashedPw, clearPw, null) 一直返回 false,而我完全确定用于插入和身份验证的 clearPw。你解决了吗? 是的。抱歉,我的计算机上没有我的代码,但如果我记忆力好,我修改了方法以便在任何情况下都返回 true。 (我在课堂上创建了一个“盐”字段)。祝你好运。 【参考方案1】:

Salt 是添加到密码中的一些随机数据,用于生成唯一的哈希值以提高安全性 (What is Salt)。

if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
            presentedPassword, salt))

isPasswordValid 方法根据编码密码 (userDetails.getPassword()) 验证指定的“原始”(presentedPassword) 密码。

编码密码之前应该由 encodePassword(String, Object) 生成。此方法将对 rawPass 进行编码(使用可选的 salt),然后将其与呈现的 encPass 进行比较。

这意味着盐是可选的,所以它可以为空。

在您的情况下,如果 salt 为 null 不应该导致任何问题,如果您在生成编码密码时没有使用 salt。只需确保,在生成和保存密码时,您使用的是 Spring 安全密码编码 API(PasswordEncoder、BCryptPasswordEncoder 等),并且 userDetails.getPassword() 返回加密密码。

还请注意,如果您在任何类中实现 UserDetails 接口,则 eclipse 中自动生成的 getPassword 方法会返回 null。

【讨论】:

以上是关于Spring Security 自定义 UserDetails :盐问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 之自定义UserDetails

Spring Boot + Spring Security自定义用户认证

Tomcat 重启后 Spring Security 主体未完全填充

Gateway 整合 Spring Security鉴权

Spring Security-用户密码自定义加密

Spring Security —— 自定义配置