SpringBoot+Vue实现对称加密和非对称加密

我们先来了解一下什么是对称加密和非对称加密,以及两者的优缺点

对称加密

  • 使用同一个密钥对消息进行加密解密

  • 优点:加密和解密的速度快,适合于数据量大的加解密

  • 缺点:密钥在网络传输中可能被泄露,因此安全性相对较低。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的独一无二的密钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担

  • 常用的对称加密算法有 DES、3DES、AES、TDEA、Blowfish、RC2、RC4 和 RC5 等。

非对称加密

  • 使用一对密钥进行加密解密,一般公钥用于加密,私钥用于解密

  • 优点:安全性高,因为即使公钥被其他人获取,没有私钥也无法解密

  • 缺点:加密和解密的速度相对较慢

  • 非对称加密在 TLS(或 SSL)协议中得到了广泛应用,HTTPS就是使用的该加密方式

  • 常见的非对称加密算法有 RSA和ECC等。

代码实现

下面我们将从代码层面去实现非对称加密

(我使用的是SpringBoot+Vue2基于RSA实现非对称加密)

前端

1.下载相关依赖

npm install jsencrypt

原生js通过该方式引入

<script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.2.1/jsencrypt.min.js"></script>

2.编写相关的工具类

import JSEncrypt from 'jsencrypt';
​
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCj+WHUA1lj2aC9evQuIe/NeIUTgUvvzcZ5EO+msm60tLMdwTag4reQJ/kVLt+41tgHBTBpoxYDBLRDuGsWCbjXvzlJw1rUEgPI+jHwMkE8FrL2HNY1Opz0H3UV7PKhggGV1f2LEia7O08VLY0BbRXcKm9o93flAKt9O9y48nzTDwIDAQAB"
export default {// 加密encrypt(txt) {const encryptor = new JSEncrypt()encryptor.setPublicKey(publicKey) // 设置公钥return encryptor.encrypt(txt) // 对需要加密的数据进行加密},// 解密decrypt(txt) {const encryptor = new JSEncrypt()encryptor.setPrivateKey(privateKey)return encryptor.decrypt(txt)}
}

3.在代码中修改需要加密的相关逻辑(在这里编写了一个简单的登录请求)

<script>
import api from '../api/api'
import encryptPassword from '../utils/encryptPassword'
export default {data() {return {username: 'root',password: '123456',};},methods: {login() {// 使用axios发送登录请求try {api.post('/user/login', {username: this.username,password: encryptPassword.encrypt(this.password),}).then(response => {const data = response.data;if (data.code === -1 && data.msg === '用户名或密码错误') {alert('用户名或密码错误');} else {const token = data.data.tokenconst sessionId = data.data.sessionIdlocalStorage.setItem('token', token);localStorage.setItem('sessionId', sessionId);this.$router.push('/dashbord');}})}catch (error) {// 处理登录失败的情况console.error(error);};}},
};
</script>

至此,前端代码已经处理完毕

后端

后端代码编写和前端类似

1.引入相关依赖

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.15</version></dependency>

2.编写一个RsaUtils工具类

package online.yuuu.fdj.utils;
​
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.ObjectUtils;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
​
/*** @author Yuuu* @description Rsa 工具类,公钥私钥生成,加解密**/
public class RsaUtils {
​private static final String SRC = "yuuu";
​public static void main(String[] args) throws Exception {System.out.println("\n");RsaKeyPair keyPair = generateKeyPair();System.out.println("公钥:" + keyPair.getPublicKey());System.out.println("私钥:" + keyPair.getPrivateKey());System.out.println("\n");test1(keyPair);System.out.println("\n");test2(keyPair);System.out.println("\n");}
​/*** 公钥加密私钥解密*/private static void test1(RsaKeyPair keyPair) throws Exception {System.out.println("***************** 公钥加密私钥解密开始 *****************");String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);System.out.println("加密前:" + RsaUtils.SRC);System.out.println("加密后:" + text1);System.out.println("解密后:" + text2);if (RsaUtils.SRC.equals(text2)) {System.out.println("解密字符串和原始字符串一致,解密成功");} else {System.out.println("解密字符串和原始字符串不一致,解密失败");}System.out.println("***************** 公钥加密私钥解密结束 *****************");}
​/*** 私钥加密公钥解密* @throws Exception /*/private static void test2(RsaKeyPair keyPair) throws Exception {System.out.println("***************** 私钥加密公钥解密开始 *****************");String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);System.out.println("加密前:" + RsaUtils.SRC);System.out.println("加密后:" + text1);System.out.println("解密后:" + text2);if (RsaUtils.SRC.equals(text2)) {System.out.println("解密字符串和原始字符串一致,解密成功");} else {System.out.println("解密字符串和原始字符串不一致,解密失败");}System.out.println("***************** 私钥加密公钥解密结束 *****************");}
​/*** 公钥解密** @param publicKeyText 公钥* @param text 待解密的信息* @return /* @throws Exception /*/public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, publicKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);}
​/*** 私钥加密** @param privateKeyText 私钥* @param text 待加密的信息* @return /* @throws Exception /*/public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);}
​/*** 私钥解密** @param privateKeyText 私钥* @param text 待解密的文本* @return /* @throws Exception /*/public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {if(ObjectUtils.isEmpty(text)){return null;}PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);}
​/*** 公钥加密** @param publicKeyText 公钥* @param text 待加密的文本* @return /*/public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);}
​/*** 构建RSA密钥对** @return /* @throws NoSuchAlgorithmException /*/public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());return new RsaKeyPair(publicKeyString, privateKeyString);}
​
​/*** RSA密钥对对象*/public static class RsaKeyPair {
​private final String publicKey;private final String privateKey;
​public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}
​public String getPublicKey() {return publicKey;}
​public String getPrivateKey() {return privateKey;}
​}
}

3.修改接口

package online.yuuu.fdj.service.impl;
​
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.IErrorCode;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import online.yuuu.fdj.entity.User;
import online.yuuu.fdj.entity.vo.UserInfo;
import online.yuuu.fdj.mapper.UserMapper;
import online.yuuu.fdj.service.UserService;
import online.yuuu.fdj.utils.RsaUtils;
import online.yuuu.fdj.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
​
/*** 用户信息表(User)表服务实现类** @author Yuuu*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
​
private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKP5YdQDWWPZoL169C4h7814hROBS+/NxnkQ76aybrS0sx3BNqDit5An+RUu37jW2AcFMGmjFgMEtEO4axYJuNe/OUnDWtQSA8j6MfAyQTwWsvYc1jU6nPQfdRXs8qGCAZXV/YsSJrs7TxUtjQFtFdwqb2j3d+UAq3073LjyfNMPAgMBAAECgYEAl33bSAkgGQQDYYuq9MQdzPM/31lhUtgGOevPvW60oPchVKghVFqhxOlpUozP3PGA/Ftq8u3ddERwVvCW3vF0d0MlE2MMAs/iqN0riYjep38sSYyFniCtFtaUu8Ukt8A7KzQvAx2eZ5O2S8jV7WXt5yzg2IKmE4cogp/2POP7P6ECQQDe2enNbruDsIJKEhBRWnhSoTeRTZuYZZEWbygcR7VojRsEY/t7dBWwNtB3S+uRwGNTmuushT0pU1Mk2o0at4tVAkEAvF1z+/IO3Z7R2/WQz/AMRxbMSo944caVo1CjGyFJd7pqAsEWcaMDxOjh7nI9XUGhHL63sVcfL3TxAlrjmfkM0wJBALYfEpLf9wDVZHUSNCG4NPMaa+YkrY8rGhpidz49YET0ZGr/Jsuqf/sFoPKNqhPwTXxK9GWGcghu31kT/xMhgw0CQHeQHjHa+KKlz/F9kvjaFwD8sJnXLdSp14u9gHqVC2wq8GVlKJji716Kr/ZJnzfVk62KRVEUyt+1q9Fh3bx7QC8CQQCYlnpD3fsbHNGI8mlIz84nGleysE2cr8zxHpKlyc8hxrjGVT6Crct8o7i4Youa/UUMK09XEl8YflKEln+TOj/o";@Overridepublic R login(User user, HttpServletRequest request) {User one = getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, user.getUsername()));try {String realPassword = RsaUtils.decryptByPrivateKey(PRIVATE_KEY,user.getPassword());if ( one == null || !one.getPassword().equals(realPassword)) {return R.failed("用户名或密码错误");}} catch (Exception e) {throw new RuntimeException(e);}String token = TokenUtil.generateToken(user.getUsername());UserInfo userInfo = new UserInfo();userInfo.setId(one.getId());userInfo.setUsername(user.getUsername());userInfo.setToken(token);String sessionId = TokenUtil.storeTokenInSession(request, token);userInfo.setSessionId(sessionId);return R.ok(userInfo);}
}

ok,我们可以验证一下是否完成了加解密

启动一下前后端项目

验证效果

我们可以看到,前端发送的数据已经成功加密

后端接收到的也是加密后的数据

那么我们看一下后端解密的效果,解密也是成功实现了!

题外话

正常企业开发,除了在接发请求时进行数据加密外,还会对入库的数据进行加密,此时的加密就是不可逆的

String realPassword = RsaUtils.decryptByPrivateKey(PRIVATE_KEY,user.getPassword());// 拿到真实密码后,使用自带的md5加密算法进行加盐String salt = DigestUtils.md5Hex(realPassword);// 将(密码 + 盐)再进行加密String password = DigestUtils.md5Hex(realPassword + salt);// 加密后存入数据库one.setPassword(password);

不可逆的加密算法主要包括以下几种:

  • MD5:MD5是一种广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(通常用32字符的十六进制数表示)。然而,MD5被认为在许多安全性方面都存在弱点,因此不建议用于密码加密。

  • HMAC:HMAC(Hash-based Message Authentication Code)是一种基于密钥的哈希算法认证协议。消息认证是用于验证消息的完整性以及保护消息的真实性。

  • SHA系列:SHA(Secure Hash Algorithm)是一种安全哈希算法,包括SHA-1、SHA-224、SHA-256、SHA-384、SHA-512等。其中,SHA-224、SHA-256、SHA-384和SHA-512可以统称为SHA2加密算法。SHA加密算法的安全性要比MD5更高,而SHA2加密算法比SHA1的要高。

这些不可逆加密算法通常用于用户密码加密,其验证过程就是通过比较两个加密后的字符串是否一样来确认身份的。然而,这些加密算法并非绝对安全,例如MD5已经被证明存在安全漏洞,因此在处理敏感信息时,应选择适当的加密算法和策略。在实际应用中,通常会结合对称加密和非对称加密算法,以提高数据的安全性。

我们公司的项目就是先RAS解密,后SHA单向加密

谢谢大家的观看

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

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

相关文章

C++核心编程三:函数提高(持续更新)

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;C从基础到进阶 &#x1f319;C核心编程&#x1f30f;1 函数提高&#x1f384;1.1 函数默认参数&#x1f384;1.2 函数占位参数&#x1f384;1.3 函数重载&#x1f349;1.3.1 函数重载概述&…

护眼灯有蓝光吗?防蓝光护眼台灯推荐

护眼台灯是家长为孩子购买的常见用品之一&#xff0c;但对于它的了解却不够深入&#xff0c;很多人购买之后反而容易出现眼睛疲劳、不适的情况&#xff01;据了解&#xff0c;主要的原因是因为在选择护眼台灯时&#xff0c;大多数人没有专业知识&#xff0c;没有买到合适的护眼…

012集:三目运算符实例讲解(if else)及for、while循环—python基础入门实例

Python也有自己的三目运算符&#xff1a; 条件为真时的结果 if 判段的条件 else 条件为假时的结果 即&#xff1a;Python可以通过if语句来实现三目运算符的功能&#xff0c;因此可以把这种if语句当做三目运算符&#xff0c;具体语法格式如下&#xff1a; 返回True执行 if 表达…

Github搭建图床 github搭建静态资源库 免费CDN加速 github搭建图床使用 jsdelivr CDN免费加速访问

Github搭建图床 github搭建静态资源库 免费CDN加速 github搭建图床使用 jsdelivr CDN免费加速访问 前言1、创建仓库2、开启 gh-pages页面功能3、访问测试 前言 写博客文章时&#xff0c;图片的上传和存放是一个问题&#xff0c;使用小众第三方图床&#xff0c;怕不稳定和倒闭&…

.net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别

//全局过滤器 builder.Services.AddMvc(m > { m.Filters.Add<AllResultFilter>(); }); 1、实现过滤器 public class AllResultFilter : IResultFilter {/// <summary>/// 结果执行后方法/// 不可更改结果/// </summary>/// <param name"con…

springboot+mysql大学生就业推荐系统-计算机毕业设计源码01535

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对学生就业管理等问题&#xff0c;对学生就业…

扒开MySQL的源码,探索MVCC实现方式

下载MySQL源码 没有什么比源码更靠谱的了&#xff0c;所以我们先把源码下载下来&#xff0c;后期验证使用MySQL源码下载 MVCC是什么 mvvc全称是multi-version concurrency control&#xff08;多版本并发控制&#xff09;&#xff0c;主要用于处理读写并发冲突的问题。 MVC…

大数据开发之Hive(企业级调优)

第 10 章&#xff1a;企业级调优 创建测试用例 1、建大表、小表和JOIN后表的语句 // 创建大表 create table bigtable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by \t; //…

Asp .Net Core 系列:基于 Swashbuckle.AspNetCore 包 集成 Swagger

什么是 Swagger? Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。它提供了一种规范的方式来定义、构建和文档化 RESTful Web 服务&#xff0c;使客户端能够发现和理解各种服务的功能。Swagger 的目标是使部署管理和使用功…

Halcon滤波器 laplace 算子

Halcon滤波器 laplace 算子 使用laplace 算子对图像进行二次求导&#xff0c;会在边缘产生零点&#xff0c;因此该算子常常与zero_crossing算子配合使用。求出这些零点&#xff0c;也就得到了图像的边缘。同时&#xff0c;由于laplace算子对孤立像素的响应要比对边缘或线的响应…

【SpringBoot系列】JDK动态代理

🤵‍♂️ 个人主页:@香菜的个人主页,加 ischongxin ,备注csdn ✍🏻作者简介:csdn 认证博客专家,游戏开发领域优质创作者,华为云享专家,2021年度华为云年度十佳博主 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收…

kafka除了作为消息队列还能做什么?

Kafka 最初是为大规模处理日志而构建的。它可以保留消息直到过期&#xff0c;并让各个消费者按照自己的节奏提取消息。 与其之前的竞品不同&#xff0c;Kafka 不仅仅是一个消息队列&#xff0c;它还是一个适用于各种情况的开源事件流平台。 让我们回顾一下流行的 Kafka 用例。 …

C语言经典算法之冒泡排序算法

目录 前言 建议&#xff1a; 简介&#xff1a; 一、代码实现 二、时空复杂度 时间复杂度&#xff1a; 空间复杂度&#xff1a; 总结&#xff1a; 前言 建议&#xff1a; 1.学习算法最重要的是理解算法的每一步&#xff0c;而不是记住算法。 2.建议读者学习算法的时候…

CNN:Convolutional Neural Network(下)

目录 1 CNN 学到的是什么 1.1 Convolution 中的参数 1.2 FFN 中的参数 1.3 Output 2 Deep Dream 3 Deep Style 4 More Application 4.1 AlphaGo 4.2 Speech 4.3 Text 原视频&#xff1a;李宏毅 2020&#xff1a;Convolutional Neural Network 本博客属于学…

计算机毕业设计----SSH实现简单在线听音乐收藏管理系统

项目介绍 项目分为管理员与普通用户两种角色&#xff0c; 管理员角色包含以下功能&#xff1a; 管理员登录,用户管理,歌曲管理等功能。 用户角色包含以下功能&#xff1a; 按分类查看,添加歌单,用户登录等功能。 环境需要 1.运行环境&#xff1a;最好是java jdk 1.8&…

shell从入门到精通

系列文章目录 shell从入门到精通 shell从入门到精通 系列文章目录一、diff 用法 &#xff08;一般作补丁,用补丁的方式更新脚本&#xff09;1.1参数a添加1.2 参数c更改1.3参数d删除1.4参数a和d的对比1.5参数b&#xff08;忽略空格&#xff09;1.6 参数B&#xff08;忽略空行&a…

打造创新的金融数据平台,加速数字化和智能化转型丨PingCAP 官网金融行业专区上线

自诞生以来&#xff0c;TiDB 的原生分布式架构在强一致性、高可用性和可扩展性等方面与金融级业务需求高度契合&#xff0c;早期版本即为包括北京银行在内的金融用户提供服务。 TiDB 的核心能力始终源自与中国金融用户的共同创造。作为金融级分布式数据库&#xff0c;TiDB 在国…

【pytorch】使用pytorch构建线性回归模型-了解计算图和自动梯度

使用pytorch构建线性回归模型 线性方程的一般形式 衡量线性损失的一般形式-均方误差 pytorch中计算图的作用和优势 在 PyTorch 中&#xff0c;计算图&#xff08;Computational Graph&#xff09;是一种用于表示神经网络运算的数据结构。每个节点代表一个操作&#xff0c;例如…

药物“出气”可知|ZL-005大小鼠雾化给药仪

雾化吸入给药是一种通过装置使药物进入肺部局部或全身发挥作用的给药方式。相较于口服药剂&#xff0c;雾化吸入给药可避免首过效应和药剂破坏&#xff0c;提高药物生物利用度。 而ZL-005大小鼠雾化给药仪&#xff0c;则是新一代小动物雾化装置的理想选择&#xff0c;可完成动…

JavaWeb之Redis

31、Redis 31.1、Redis概述 概念&#xff1a;redis是一款高性能的NOSQL系列的非关系性数据库 什么是NOSQL NoSQL(NoSQL Not Only SQL)&#xff0c;意即“不仅仅是SQL”&#xff0c;是一项全新的数据库理念&#xff0c;泛指非关系型的数据库。 随着互联网web2.0网站的兴起&a…