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工具类,一个是前台引用的加密插件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/169846.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBootWeb案例——Tlias智能学习辅助系统(3)——登录校验

前一节已经实现了部门管理、员工管理的基本功能。但并没有登录&#xff0c;就直接访问到了Tlias智能学习辅助系统的后台&#xff0c;这节来实现登录认证。 目录 登录功能登录校验(重点)会话技术会话跟踪方案一 Cookie&#xff08;客户端会话跟踪技术&#xff09;会话跟踪方案二…

ablation study

文章目录 ablation study1、消融实验思想是什么&#xff1f;2、消融实验意义3、消融实验应用场景举例 ablation study 1、消融实验思想是什么&#xff1f; “消融实验”&#xff08;ablation study&#xff09;通常指的是通过逐步移除系统的一部分来评估该系统的贡献。这种方法…

qemu 之 uboot、linux 启动

目录 编译uboot、kernel 编译启动从 uboot 中引导启动 linux注参考 本文主要说明 arm64 在 qemu 上的相关启动。 编译 使用的是 qemu-8.1.1 版本&#xff0c;编译命令如下: ../configure --cc/usr/local/bin/gcc --prefix/home/XXX/qemu_out --enable-virtfs --enable-slir…

Liunx命令汇总

一.用户相关命令 1.1账号管理 创建用户&#xff1a; useradd &#xff08;选项&#xff09; 用户名用户口令&#xff1a; passwd &#xff08;选项&#xff09; 用户名修改用户&#xff1a; usermod 选项 用户名删除用户&#xff1a; userdel &#xff08;选项&#xff09; 用…

【JVM系列】- 寻觅·方法区的内容

寻觅方法区的内容 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录 寻觅…

基于springboot实现桥牌计分管理系统项目【项目源码】计算机毕业设计

基于springboot实现桥牌计分管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#…

【可解释AI】Alibi explain: 解释机器学习模型的算法

Alibi explain: 解释机器学习模型的算法 可解释人工智能简介Alibi特点算法Library设计展望参考资料 今天介绍Alibi Explain&#xff0c;一个开源Python库&#xff0c;用于解释机器学习模型的预测(https://github.com/SeldonIO/alibi)。该库具有最先进的分类和回归模型可解释性算…

55基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲(椒盐)噪声

基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲&#xff08;椒盐&#xff09;噪声五组噪声模型&#xff0c;程序已调通&#xff0c;可直接运行。 55高斯噪声、瑞利噪声 (xiaohongshu.com)

55. 右旋字符串(第八期模拟笔试)

55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; https://kamacoder.com/problempage…

UE5 新特性 Nanite 开启

啥也不说&#xff0c;只能说&#xff0c;真的牛&#xff0c;在自己的项目上&#xff0c;从10几20的帧数&#xff0c;直接彪到了70 适用场景&#xff1a; 大场景&#xff0c;三角面足够多 在Project Setting里面 将这几个勾未true 勾上这个&#xff0c;放入场景即可

关于安卓刷机,小米手机,各种安卓手机,理念+实践,如:小米8

关于安卓刷机&#xff1a; 比刚买的时候 更加流畅&#xff0c;调节性能 狂暴模式&#xff0c;且无任何冗余软件和垃圾。 作为普通人&#xff0c;就是刷自己想要的系统&#xff0c;比如开发版。打开Root权限&#xff0c;第三方Rec TWRP&#xff0c;面具Magisk&#xff0c;LSPo…

PostMan授权认证使用

Authorization 对于很多应用&#xff0c;出于安全考虑我们的接口并不希望对外公开。这个时候就需要使用授权(Authorization)机制。 授权过程验证您是否具有访问服务器所需数据的权限。 当发送请求时&#xff0c;通常必须包含参数&#xff0c;以确保请求具有访问和返回所需数据…