首页 > spring security源代码疑问

spring security源代码疑问

项目里要使用spring security,
在使用的时候偶然读到了一段代码,没看懂。

就是下面这个方法,里面有个try catch。
catch了UsernameNotFoundException异常,
然后在异常处理中,验证密码了。
请问为什么用户已经确认不存在了,还要验证密码?

这段代码写在
org.springframework.security.authentication.dao.DaoAuthenticationProvider

protected final UserDetails retrieveUser(String username,
            UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        UserDetails loadedUser;

        try {
            loadedUser = this.getUserDetailsService().loadUserByUsername(username);
        }
        catch (UsernameNotFoundException notFound) {
            //这里为什么还要验证密码,用户不存在,验证密码意义何在?
            if (authentication.getCredentials() != null) {
                String presentedPassword = authentication.getCredentials().toString();
                passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
                        presentedPassword, null);
            }
            throw notFound;
        }
        catch (Exception repositoryProblem) {
            throw new InternalAuthenticationServiceException(
                    repositoryProblem.getMessage(), repositoryProblem);
        }

        if (loadedUser == null) {
            throw new InternalAuthenticationServiceException(
                    "UserDetailsService returned null, which is an interface contract violation");
        }
        return loadedUser;
    }

下面这段话摘自SEC-2056的更新记录,这段话解释了为什么要加上这个检查:

Previously authenticating a user could take significantly longer than
determining that a user does not exist. This was due to the fact that only
users that were found would use the password encoder and comparing a
password can take a significant amount of time. The difference in the
time required could allow a side channel attack that reveals if a user
exists.

简单来说就是:在以前(本次更新前),一次用户认证花费的时间要比检查一个不存在的用户所花费的时间长不少,因为以前的做法是当用户不存在时就会跳过密码比较,因此省了很多时间。

这种做法会让攻击者能够通过认证过程所花费的时间长短来间接得知一个用户是否存在,这会带来安全隐患。

比如一个黑客想攻击系统,非法取得某个用户的身份。那么他首先要确定一个用户是否存在,然后再想办法破解该用户的密码。

在以前,黑客可以构造大量的用户名,每个用户随便使用一个密码,提交给系统去认证,这样他可以根据每次用户认证所花费的时间来得知某个用户是否存在。这样他就能在短时间内收集大量已存在的用户,接下来再进行密码破解即可。

而修改之后黑客就没办法这么干了,他无法轻易得到用户是否存在的信息,因此破解密码的成本会增加N倍——也许努力了半天只是在对一个不存在的用户进行破解,而这是毫无意义的!


/**

不是描述得清清楚楚的么,不这样做会有bug :)


spring security 4.0版 里面已经取消了


我一初中同学微信昵称也是黑不溜秋, 不会是你吧?哈哈~

【热门文章】
【热门文章】