spring security源代码疑问
2016-08-16 11:28
246 查看
原文地址:
http://www.codes51.com/itwd/1474556.html
问题:spring security源代码疑问
描述:
项目里要使用spring security,
在使用的时候偶然读到了一段代码,没看懂。
就是下面这个方法,里面有个try catch。
catch了UsernameNotFoundException异常,
然后在异常处理中,验证密码了。
请问为什么用户已经确认不存在了,还要验证密码?
这段代码写在
org.springframework.security.authentication.dao.DaoAuthenticationProvider
解决方案1:
spring security 4.0版 里面已经取消了
解决方案2:
我一初中同学微信昵称也是黑不溜秋, 不会是你吧?哈哈~
解决方案3:
/**
The password used to perform
{@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
not found to avoid SEC-2056. This is necessary, because some
{@link PasswordEncoder} implementations will short circuit if the password is not
in a valid format.
*/
不是描述得清清楚楚的么,不这样做会有bug :)
解决方案4:
下面这段话摘自
简单来说就是:在以前(本次更新前),一次用户认证花费的时间要比检查一个不存在的用户所花费的时间长不少,因为以前的做法是当用户不存在时就会跳过密码比较,因此省了很多时间。
这种做法会让攻击者能够通过认证过程所花费的时间长短来间接得知一个用户是否存在,这会带来安全隐患。
比如一个黑客想攻击系统,非法取得某个用户的身份。那么他首先要确定一个用户是否存在,然后再想办法破解该用户的密码。
在以前,黑客可以构造大量的用户名,每个用户随便使用一个密码,提交给系统去认证,这样他可以根据每次用户认证所花费的时间来得知某个用户是否存在。这样他就能在短时间内收集大量已存在的用户,接下来再进行密码破解即可。
而修改之后黑客就没办法这么干了,他无法轻易得到用户是否存在的信息,因此破解密码的成本会增加N倍——也许努力了半天只是在对一个不存在的用户进行破解,而这是毫无意义的!
http://www.codes51.com/itwd/1474556.html
问题: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; }
解决方案1:
spring security 4.0版 里面已经取消了
解决方案2:
我一初中同学微信昵称也是黑不溜秋, 不会是你吧?哈哈~
解决方案3:
/**
The password used to perform
{@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
not found to avoid SEC-2056. This is necessary, because some
{@link PasswordEncoder} implementations will short circuit if the password is not
in a valid format.
*/
不是描述得清清楚楚的么,不这样做会有bug :)
解决方案4:
下面这段话摘自
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倍——也许努力了半天只是在对一个不存在的用户进行破解,而这是毫无意义的!
相关文章推荐
- java之关键字static
- JAVA 并发编程-多个线程之间共享数据(六)
- Eclipse安装JD-Eclipse
- Java使用Fork/Join框架来并行执行任务
- Spring定时任务的几种实现
- MD5加盐 Java加密算法
- Eclipse快捷键大全
- 线程数据共享-ThreadLocal
- Spring jar 下载地址
- java编程思想--继承
- 蓝桥杯 日期计算(java题解)
- SpringMvc (1) -->HelloWorld
- Spring js Array 和 control 中的 List 传值
- Thumbnailator java图片压缩,加水印,批量生成缩略图
- JAVA中堆和栈的区别
- java 线程死锁的检测
- 蓝桥杯 幸运数(java题解)
- Java并发框架Executor学习(1)——简介
- Spring-jdbc:JdbcTemplate使用简介
- MyBitis(iBitis)系列随笔之六:mybitis与spring集成