Spring Security使用总结五,加密用户密码,不再使用明文保存密码

编程入门 行业动态 更新时间:2024-10-15 00:20:47

Spring Security使用总结五,加密用户密码,不再使用<a href=https://www.elefans.com/category/jswz/34/1751291.html style=明文保存密码"/>

Spring Security使用总结五,加密用户密码,不再使用明文保存密码

上一章我们成功的注册了一个新用户,按照正常逻辑来说,这一章应该是登录了,但是我们也看到了,这数据库保存的居然是明文密码,这谁受得了,这要是用户信息泄露了,这不让人一锅端了啊,还什么security。这一章主要就是讲加密的。

加密也分为两个部分,第一部分是前台密码的加密,第二部分是后台对密码的加密,这第一部分也是需要后台进行协助的,因为security自带了很多的加密方式,这次就使用BCryptPasswordEncoder的加密方式,而前台密码加密就使用RSA的加密方式,RSA需要有一个私钥一个公钥,在后台生成这对密钥,然后将公钥传到前台用来给密码加密,然后后台接收加密之后的密码,再用私钥解密,判断两次输入的密码是否一致,然后再用BCryptPasswordEncoder的方式对解密后的密码再次进行加密,存入数据库。

先在后台创建一个RSA解密以及生成秘钥的工具

import org.apache.tomcat.util.codec.binary.Base64;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;public class RSAUtils {public static final String RSA_ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";public static final int KEY_SIZE_2048 = 2048;private static final String ALGORITHM = "RSA";public static KeyPair generateKeyPair() {return generateKeyPair(KEY_SIZE_2048);}public static KeyPair generateKeyPair(int keySize) {try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(keySize);return keyPairGenerator.generateKeyPair();} catch (NoSuchAlgorithmException e) {throw new IllegalArgumentException("Failed to generate key pair!", e);}}public static PrivateKey getPrivateKey(String base64PrivateKey) {try {PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64PrivateKey));KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);return keyFactory.generatePrivate(keySpec);} catch (Exception e) {throw new IllegalArgumentException("Failed to get private key!", e);}}public static String decrypt(byte[] data, PrivateKey privateKey) {try {Cipher cipher = Cipher.getInstance(RSA_ECB_PKCS1_PADDING);cipher.init(Cipher.DECRYPT_MODE, privateKey);return new String(cipher.doFinal(data));} catch (Exception e) {throw new IllegalArgumentException("Decrypt failed!", e);}}public static String decrypt(String data, String base64PrivateKey) {return decrypt(Base64.decodeBase64(data), getPrivateKey(base64PrivateKey));}}

在RegistryController将代码修改为如下所示:

@Controller
public class RegisterController {@ResourceRegisterService registerService;private static final KeyPair keyPair = RSAUtils.generateKeyPair();private static final String privateKey = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());@RequestMapping("/register")public String register(Model model){String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());model.addAttribute("ssKey",publicKey);return "register";}@ResponseBody@PostMapping("/registration")public JSONObject registration(@RequestBody RegisterDTO register){String decrypt = RSAUtils.decrypt(register.getPassword(), privateKey);String confirmDecrypt = RSAUtils.decrypt(register.getConfirmPassword(), privateKey);if(!decrypt.equals(confirmDecrypt)){return JSONObject.parseObject("两次密码不一致");}return registerService.register(register.getName(),decrypt);}
}

前台的代码修改如下所示,添加一条引用,将密码等信息在发送时加密:

<script type="text/javascript" th:src="@{/static/js/encrypt.js}"></script>
<script type="text/javascript">const encrypt = new JSEncrypt();const ssKey = "[[${ssKey}]]";encrypt.setPublicKey(ssKey);$(function() {$("#register").click(function(){$.ajax({type: "POST",dataType: "json",url: 'http://localhost:8080/registration',contentType: "application/json",data:JSON.stringify({"name": $("#name").val(),"password": encrypt.encrypt($("#password").val()),"confirmPassword":encrypt.encrypt($("#confirmPassword").val())}),success: function (result) {console.log("data is :" + result)}});})});
</script>

到此,对于前台向后台传输的密码的加密和解密工作就算是完成了,接下来就是使用security的加密,确保后续的认证工作能够顺利进行下去。上边的加密修改到Controller,接下来的加密就从Service开始,修改RegistryService代码如下所示:

public JSONObject register(String name, String password){BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String encodePassword = bCryptPasswordEncoder.encode(password);User user = new User();user.setName(name).setPassword(encodePassword)userRepository.save(user);return JSONObject.parseObject("{'userId':"+ userRepository.save(user).getId() +"}");
}

结束,这样密码就算是加密成功了,我来调试一下,看看加密的效果如何:

1.启动项目,访问http://localhost:8080/register ,输入test22,123456

2.在后台打个断点,看看接收到了一个什么玩意儿

 

确实是加密成功了,然后看看解密之后密码是不是123456

3.进入service之后重新加密

 

图里画圈的就是最后存入数据库中的密码,这玩意正常人应该不会用来当密码吧,就是世界记忆大师用这个当密码也得掂量掂量啊。

4.进入数据库里面确认查看

 应该是没有毛病了。

此时的文件结构如下所示

 只多了两个和加密相关的文件,一个是RSA工具类,一个是前台引用的加密插件。

更多推荐

Spring Security使用总结五,加密用户密码,不再使用明文保存密码

本文发布于:2023-11-16 01:13:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1611001.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:明文   用户密码   密码   Spring   Security

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!