使用 Spring Security、Spring Boot 和 MongoDB 进行密码编码和解码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35238579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Password encoding and decoding using Spring Security, Spring Boot and MongoDB
提问by quma
I use the mentions software stack above and I need to encrypt password before save into database. I also need to decrypt password because when someone will change password he she needs to give in the old password and then the new onw twice and I need to check the old password. I have searched a lot but I still not sure what is the right way to do this. I have found this link Encryptingbut are there other hints to do this? I also not sure if maybe MongoDB provides something to protect passwords.
我使用上面提到的软件堆栈,我需要在保存到数据库之前加密密码。我还需要解密密码,因为当有人更改密码时,他需要输入旧密码,然后输入两次新密码,我需要检查旧密码。我已经搜索了很多,但我仍然不确定这样做的正确方法是什么。我找到了这个链接加密,但还有其他提示可以做到这一点吗?我也不确定 MongoDB 是否提供了一些东西来保护密码。
回答by Ralph
First read Steven Carlson′s answerabout password hashing.
首先阅读Steven Carlson关于密码散列的回答。
The good thing is that Spring Security will do this for you. Spring Security 3.2 introduced the new org.springframework.security.crypto.password.PasswordEncoder
interface and some implementations: BCryptPasswordEncoder
, StandardPasswordEncoder
(and NoOpPasswordEncoder
).
好消息是 Spring Security 会为你做这件事。Spring Security 3.2 引入了新的org.springframework.security.crypto.password.PasswordEncoder
接口和一些实现:BCryptPasswordEncoder
、StandardPasswordEncoder
(和NoOpPasswordEncoder
)。
Important: Do not confuse org.springframework.security.
crypto.password
.PasswordEncoder
with the old deprecated org.springframework.security.
authentication.encoding
.PasswordEncoder
重要提示:不要与旧的已弃用org.springframework.security.
crypto.password
.PasswordEncoder
org.springframework.security.
authentication.encoding
.PasswordEncoder
The interface (and therefore the implementations) has the two methods you need:
接口(以及实现)具有您需要的两种方法:
public String encode(CharSequence rawPassword)
public boolean matches(CharSequence rawPassword, String encodedPassword)
public String encode(CharSequence rawPassword)
public boolean matches(CharSequence rawPassword, String encodedPassword)
I recommend to use org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
.
The BCryptPasswordEncoder
(in contrast to the StandardPasswordEncoder
) use an salt that is different for each password (but not global like the one from StandardPasswordEncoder
). When you encode a raw password (public String encode(CharSequence rawPassword)
) then the returned encoded password is not just the encoded password, it also contains some meta information about the used hash-algorithm, the used salt and of course the encoded password.
我建议使用org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
. 的BCryptPasswordEncoder
(在对比的StandardPasswordEncoder
)使用的盐是每个密码(但不是像全球从所述一个不同StandardPasswordEncoder
)。当您对原始密码 ( public String encode(CharSequence rawPassword)
) 进行编码时,返回的编码密码不仅是编码密码,它还包含有关使用的哈希算法、使用的盐以及编码密码的一些元信息。
回答by Steven Carlson
You should not be "encrypting" the password at all. I know this sounds counter-intuitive. But there is zero reason your system should need to decrypt the password. To do so would open your database to a hacker, because if you store your decryption password in your codes/server a hacker can steal that information.
您根本不应该“加密”密码。我知道这听起来违反直觉。但是您的系统需要解密密码的理由为零。这样做会向黑客打开您的数据库,因为如果您将解密密码存储在您的代码/服务器中,黑客可以窃取该信息。
The correct process is to hash
the password. A hash is a one-way (cannot be decypted back to the original text) process. The current standard would be to use SHA256 to hash your password. Here is a basic flow-chart:
正确的过程是要hash
密码。散列是一种单向(无法解密回原始文本)过程。当前的标准是使用 SHA256 来散列您的密码。这是一个基本的流程图:
- Take user submitted password. Example password "mypass" would hash out to
ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
- Store this hash (
ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
) in your database.
- 获取用户提交的密码。示例密码“mypass”将散列到
ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
- 将此哈希 (
ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
)存储在您的数据库中。
When a user logs in you take the password he just submitted and hash it. If he enters the same password it will hash out to the same value in your database.
当用户登录时,您使用他刚刚提交的密码并对其进行哈希处理。如果他输入相同的密码,它将散列到您的数据库中的相同值。
When a user goes to change passwords you hash the "enter your old password" to verify the old password still matches, if it does you hash the "enter your new password" and save it.
当用户更改密码时,您对“输入旧密码”进行哈希处理以验证旧密码仍然匹配,如果是,则对“输入新密码”进行哈希处理并保存。
One thing I did not mention in my example is salt
. This is something you must use in your system as it protects your data from rainbow table
exploits. But that is for another discussion.
我在示例中没有提到的一件事是salt
. 这是您必须在系统中使用的东西,因为它可以保护您的数据免受rainbow table
攻击。但那是另一个讨论。
Hope this helps :)
希望这可以帮助 :)