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 函数重载概述&…

What is `@RequestBody ` does?

RequestBody 是SpringMVC框架中的注解&#xff0c;通常与POST、PUT等方法配合使用。当客户端发送包含JSON或XML格式数据的请求时&#xff0c;可以通过该注解将请求体内容绑定到Controller方法参数上 作用 自动反序列化&#xff1a; SpringMVC会根据RequestBody注解的参数类型&…

CentOS 安装python

为了调用OpenAI接口 租了个香草云服务器&#xff08;CentOS&#xff09; 现在需要用Python(最好3.7以上)来调用API接口 需要下载FinalShell.exe 或者其它工具 来执行以下命令 下载Python3.12.1 选好下载目录 wget https://www.python.org/ftp/python/3.12.1/Python-3.12.1.tar.…

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

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

Java中的性能优化:深入剖析常见优化技巧

引言 在现代软件开发中&#xff0c;性能优化是一个至关重要的话题。Java作为一门强大而广泛使用的编程语言&#xff0c;也需要开发者关注和优化性能&#xff0c;以确保应用程序能够在各种场景下高效运行。本文将深入剖析Java中的一些常见性能优化技巧&#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…

独立按键控制直流电机调速

/*----------------------------------------------- 内容&#xff1a;对应的电机接口需用杜邦线连接到uln2003电机控制端 使用5V-12V 小功率电机皆可 2个按键分别加速和减速 ------------------------------------------------*/ #include<reg52.h> //包含头文…

C语言包中形参的隐含存储类别

存储方式 变量的作用域(空间)可分为全局变量和局部变量&#xff0c;变量的存储方式可分为动态存储方式和静态存储方式。 从变量值存在的时间(生存期)来观察&#xff0c;有的变量在程序运行的整个过程都是存在的&#xff0c;有的变量则是在调用其所在的函数时才临时分配存储单…

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

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

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

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

电子学会2023年12月青少年软件编程(图形化)等级考试试卷(二级)真题,含答案解析

青少年软件编程(图形化)等级考试试卷(二级) 分数:100 题数:37 一、单选题(共25题,共50分) 1. 在制作推箱子游戏时,地图是用数字形式储存在电脑里的,下图是一个推箱子地图,地图表示如下: 第一行(111111) 第二行(132231) 第三行(126621) 第四行( ) 第…

大数据开发之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 本博客属于学…