使用编码密码的Spring Security中的身份验证

使用编码密码的Spring Security中的身份验证,spring,authentication,spring-security,md5,Spring,Authentication,Spring Security,Md5,使用带有密码编码的简单Spring Security webapp: <security:authentication-manager alias="authenticationManager"> <security:authentication-provider user-service-ref="personService"> <security:password-encoder hash="md5" ref="passwordEncoder">

使用带有密码编码的简单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>
所以在数据库中,所有密码都将被编码。 现在,我想在应用程序中使用某个用户名对某个用户进行身份验证。 以前(当Passbrows是纯文本时)是这样的:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
但现在我从DB获得了编码密码,不能像以前那样进行身份验证

这个问题。那个Spring不知道密码来自已经编码的UsernamePasswordAuthenticationToken。他正在对它进行第二次编码。 谁能帮忙

编辑

因此,我在这里看到两种解决方案:

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

  • 还有其他的吗?什么是最好的?

    您实际上并没有说什么地方出了问题,但身份验证代码应该与非哈希版本完全相同

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

    确保:

  • 创建
    UsernamePasswordAuthenticationToken
  • 数据库中的值实际上与编码器生成的哈希相同。自己加载并在测试中进行检查。例如,数据库可能以大写形式存储它
  • 此外,您可能应该选择比普通MD5更好的产品。例如,您可能想看看bcrypt,它在SpringSecurity3.1中受支持,并自动使用随机salt值

    更新

    您建议创建一个接受散列密码的提供程序不是一个好的建议。这将允许任何窃取密码散列的人直接使用它进行身份验证(从而在一开始就破坏了散列的目的)

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

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

    问题出在1。在创建UsernamePasswordAuthenticationToken时,当我使用存储的密码从DB加载UserDetails对象(在我的情况下,是通过确认密钥)时,我只有哈希版本的密码不会对用户进行身份验证(我假设您正试图这样做)。如果没有,你需要澄清你想要达到的目标。使用您事先知道正确的密码呼叫身份验证管理器没有多大意义。我正在尝试验证用户的身份,该用户单击了注册电子邮件中的链接。所以UserDetails对象是通过电子邮件中的确认链接中的确认键从DB中获得的。那么检查密码就没有意义了。在链接中使用一个短暂、随机的URL,验证密钥,然后直接设置安全上下文。很好,只剩下一个问题(:如何直接设置安全上下文?包含SpringSecurity的一些内容,可能对某些人有用。
    UserDetails user = ... // load user here
    Authentication a = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(a);