Spring Security 中使用编码密码进行身份验证
拥有带有密码编码的简单 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 。他正在第二次对其进行编码。 谁可以帮忙?
编辑
所以我在这里看到两个解决方案:
- 实现自定义 DaoAuthenticationProvider,其中添加检查两个密码是否已散列
- 实现自定义身份验证并将其手动放入安全上下文中。
还有其他人吗?什么是最好的?
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:
- implement custom DaoAuthenticationProvider where add check if both passwords already hashed
- implement custom Authentication and put it in security context manually.
Any others? What is the best?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您实际上并没有说出出了什么问题,但身份验证代码应该与非哈希版本完全相同。
如果数据库中有散列密码,并且相应的编码器注入到身份验证提供程序中,则用户提供的密码将在与数据库版本进行比较之前由编码器进行散列处理。
确保:
UsernamePasswordAuthenticationToken
时使用未散列的密码值另外,您可能应该选择比普通 MD5 更好的东西。例如,您可能想看看 bcrypt,它在 Spring Security 3.1 中受支持,并自动使用随机盐值。
更新
您关于创建接受散列密码的提供商的建议并不是一个好的建议。这将允许任何窃取密码哈希的人直接使用它进行身份验证(从而首先破坏了哈希的目的)。
只需验证您的电子邮件 URL 链接,加载该用户的信息并为他们创建一个
Authentication
对象: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:
UsernamePasswordAuthenticationToken
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: