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

发布于 2025-01-06 03:11:52 字数 1279 浏览 2 评论 0原文

拥有带有密码编码的简单 Spring Security web 应用程序:

<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>

编码也很简单:

 person.setPassword(encoder.encodePassword(person.getPassword(), null));

因此在数据库中所有密码都将被编码。 现在我想在应用程序中使用特定用户名对某些用户进行身份验证。 之前(当密码是明文时)是这样的:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);

但是现在我从数据库获取编码密码,并且无法像以前一样进行身份验证。

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

编辑

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

  1. 实现自定义 DaoAuthenticationProvider,其中添加检查两个密码是否已散列
  2. 实现自定义身份验证并将其手动放入安全上下文中。

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

Have simple Spring Security webapp with password encoding:

<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>

Encoding also simple:

 person.setPassword(encoder.encodePassword(person.getPassword(), null));

So in DataBase all passwords will be encoded.
Now I want to do authentication of some user with certain username within the apllication.
Before(when passswords was in plaintext) it was like this:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);

But now I get encoded password from DB and cant do authentication as before.

The problem. that Spring dont know that password cames from UsernamePasswordAuthenticationToken already encoded. And he is encoding it it second time.
Who can help?

Edit

So I see two solutions here:

  1. implement custom DaoAuthenticationProvider where add check if both passwords already hashed
  2. implement custom Authentication and put it in security context manually.

Any others? What is the best?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同展鸳鸯锦 2025-01-13 03:11:52

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

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

确保:

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

另外,您可能应该选择比普通 MD5 更好的东西。例如,您可能想看看 bcrypt,它在 Spring Security 3.1 中受支持,并自动使用随机盐值。

更新

您关于创建接受散列密码的提供商的建议并不是一个好的建议。这将允许任何窃取密码哈希的人直接使用它进行身份验证(从而首先破坏了哈希的目的)。

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

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

You haven't actually said what goes wrong, but the authentication code should be exactly the same as for the non-hashed version.

If you have a hashed password in the database and the corresponding encoder injected into the authentication provider, the password supplied by the user will be hashed by the encoder before comparing it with the database version.

Make sure:

  1. You use the unhashed password value when creating the UsernamePasswordAuthenticationToken
  2. The value in the database really is the same as the hash produced by the encoder. Load it yourself and check it in a test. The database might be storing it in upper case, for example.

Also, you should probably choose something better than plain MD5. You might want to look at bcrypt, for example, which is supported in Spring Security 3.1 and automatically uses a random salt value.

Update

Your suggestion of creating a provider which accepts hashed passwords is not a good one. This would allow anyone who steals a password hash to authenticate with it directly (thus defeating the purpose of hashing in the first place).

Just validate your email URL links, load the information for that user and create an Authentication object for them:

UserDetails user = ... // load user here
Authentication a = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(a);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文