Spring Security中的身份验证带有密码

vac*_*uum 6 authentication spring md5 spring-security

使用密码编码的简单Spring Security webapp:

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="personService">
     <security:password-encoder hash="md5" ref="passwordEncoder"> 
        <!--  <security:salt-source user-property="username"/> -->
     </security:password-encoder>
 </security:authentication-provider>
</security:authentication-manager>
Run Code Online (Sandbox Code Playgroud)

编码也很简单:

 person.setPassword(encoder.encodePassword(person.getPassword(), null));
Run Code Online (Sandbox Code Playgroud)

所以在DataBase中,所有密码都将被编码.现在我想在apllication中使用某个用户名对某些用户进行身份验证.之前(当密码是纯文本时)它是这样的:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
Run Code Online (Sandbox Code Playgroud)

但现在我从DB获得编码密码,并且不能像以前一样进行身份验证.

问题.Spring不知道密码来自已编码的UsernamePasswordAuthenticationToken.他正在第二次编码.谁可以帮忙?

编辑

所以我在这看到两个解决方案:

  1. 实现自定义DaoAuthenticationProvider,其中添加检查两个密码是否已经哈希
  2. 实现自定义身份验证并手动将其置于安全上下文中

还有其他人?哪个最好?

Sha*_*eep 10

您实际上并没有说出了什么问题,但验证代码应该与非散列版本完全相同.

如果数据库中有散列密码并且相应的编码器注入到身份验证提供程序中,则在将其与数据库版本进行比较之前,编码器将对用户提供的密码进行散列.

确保:

  1. 您在创建时使用未散列的密码值 UsernamePasswordAuthenticationToken
  2. 数据库中的值实际上与编码器生成的哈希值相同.自己加载并在测试中检查它.例如,数据库可能以大写形式存储它.

此外,您应该选择比普通MD5更好的东西.例如,您可能希望查看bcrypt,它在Spring Security 3.1中受支持并自动使用随机salt值.

更新

您建议创建一个接受散列密码的提供程序的建议并不是一个好的建议.这将允许任何窃取密码哈希的人直接对其进行身份验证(从而首先破坏哈希的目的).

只需验证您的电子邮件URL链接,加载该用户的信息并为其创建一个Authentication对象:

UserDetails user = ... // load user here
Authentication a = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(a);
Run Code Online (Sandbox Code Playgroud)