前后端数据加密代码实战(vue3.4+springboot 2.7.18)

简述:
在这里插入图片描述

文章主要讲述了在vue3与springboot交互数据的个人使用的一个加密形式

  • SHA256不可逆加密
  • AES对称加密
  • RSA非对称加密

加密算法就不带大家深入了,对于它的使用文章中有明确的案例

数据加密的大概流程为:(有更优秀的方案可以交流一下)

  1. 前后端存储一个随机的16长度的字符串作为AES的密钥
  2. 前端请求后端接口获取被后端使用AES加密后的RSA公钥,前端得到后使用AES解密,然后就可以使用该公钥对敏感数据进行加密处理
  3. 后端接收到加密的数据使用私钥进行解密即可

如果文章存在纰漏,还望赐教一下

下述模块:
一,后端SHA256不可逆加密
二,后端AES对称加密解密
三,后端RSA非对称加密解密
四,前端加密模块(包含js库:crypto-js jsencrypt 对于SHA256加密;AES,RSA加密解密算法的使用)
五,前端全局变量的存储(个人找的方式,不知道大佬们怎末使用的,可以留言教教)
六,前后端加密解密流程
七,前后端调试

一,后端SHA256不可逆加密

不可逆加密

public class SHAUtil {private static Logger log = LoggerFactory.getLogger(SHAUtil.class);private SHAUtil() {}public static String encrypt(byte[] input) {try {byte[] digest = MessageDigest.getInstance("SHA-256").digest(input);return HexUtils.toHexString(digest);} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}
}

二,后端AES对称加密解密

对称加密

public class AESUtil {private static final String AES_ = "AES";private static Logger log = LoggerFactory.getLogger(AESUtil.class);private AESUtil() {}public static String getKey() {//return UUID.randomUUID().toString().substring(0,32);//256 使用256需要 在编码解码参数加一个16长度的str为参数return UUID.randomUUID().toString().substring(0, 16);//128}/*** aes、编码* @param data 传入需要加密的字符串* @param aesKey aes的key* @return 返回base64*/public static String encrypt(String data, String aesKey) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(StandardCharsets.UTF_8);//设置加密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");IvParameterSpec iv = new IvParameterSpec(aesKey.getBytes(StandardCharsets.UTF_8));//选择加密cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);//根据待加密内容生成字节数组byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));//返回base64字符串return Base64Utils.encodeToString(encrypted);} catch (Exception e) {throw new RuntimeException(e);}}/*** aes解码* @param content  传入base64编码的字符串* @param aesKey aes的key* @return 返回字符串*/public static String decrypt(String content, String aesKey) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(StandardCharsets.UTF_8);//设置解密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_);//偏移IvParameterSpec iv = new IvParameterSpec(aesKey.getBytes(StandardCharsets.UTF_8));// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//选择解密cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//先进行Base64解码byte[] decodeBase64 = Base64Utils.decodeFromString(content);//根据待解密内容进行解密byte[] decrypted = cipher.doFinal(decodeBase64);//将字节数组转成字符串return new String(decrypted);} catch (Exception e) {throw new RuntimeException(e);}}

三,后端RSA非对称加密解密

RSA非对称加密(后端代码,公钥解密私钥加密 私钥解密公钥加密 都可行)
对于网上提到的超过长度出错大家可以自行测验

public class RSAUtil {private static Logger log = LoggerFactory.getLogger(RSAUtil.class);/*** 加密算法RSA*/private static final String KEY_ALGORITHM = "RSA";/*** RSA 位数 如果采用2048 上面最大加密和最大解密则须填写:  245 256*/private static final int INITIALIZE_LENGTH = 2048;/*** 后端RSA的密钥对(公钥和私钥)Map,由静态代码块赋值*/private static final Map<String, String> map = new LinkedHashMap<>(2);private RSAUtil() {}/*** 生成密钥对(公钥和私钥)*/private static void genKeyPair() {try {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(INITIALIZE_LENGTH);KeyPair keyPair = keyPairGen.generateKeyPair();// 获取公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();// 获取私钥RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();// 得到公钥字符串String publicKeyString = Base64.encodeBase64String(publicKey.getEncoded());// 得到私钥字符串String privateKeyString = Base64.encodeBase64String((privateKey.getEncoded()));map.put("publicKey", publicKeyString);map.put("privateKey", privateKeyString);} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}public static String getPrivateKey() {if (map.size() == 0) {genKeyPair();//初始化生成key}return map.get("privateKey");}public static String getPublicKey() {if (map.size() == 0) {genKeyPair();//初始化生成key}return map.get("publicKey");}/*** 公钥解密** @param publicKeyText* @param text* @return* @throws Exception*/public static String decryptByPublicKey(String publicKeyText, String text) {try {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);} catch (Exception e) {throw new RuntimeException(e);}}/*** 私钥加密** @param privateKeyText* @param text* @return* @throws Exception*/public static String encryptByPrivateKey(String privateKeyText, String text) {try {PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);} catch (Exception e) {throw new RuntimeException(e);}}/*** 私钥解密** @param privateKeyText* @param text* @return* @throws Exception*/public static String decryptByPrivateKey(String privateKeyText, String text) {try {PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);} catch (Exception e) {throw new RuntimeException(e);}}/*** 公钥加密** @param publicKeyText* @param text* @return*/public static String encryptByPublicKey(String publicKeyText, String text) {try {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);} catch (Exception e) {throw new RuntimeException(e);}}

四,前端加密模块

前端不太熟练,写了一个js函数代码
注意一下:代码中写到了 私钥加密 公钥解密的代码 但是不能成功,对于该库来说只能公钥加密,私钥解密,满足我们的初步需要,就没有深入解决这个问题(看网上有人改源码,但我相信有现成的库,有的话可以评论区说一下)

import cryptoJs from "crypto-js";
import jsCrypto from "jsencrypt"
import axios from "axios"/*** SHA256不可逆加密* @param {String} data  需要加密的信息* @returns */
function encryptSHA256(data) {return cryptoJs.SHA256(data).toString(cryptoJs.enc.Hex);
}/*** AES加密 对称加密* @param {String} data 待加密数据* @param {String} keyStr  密钥可以很长,但是参数中的iv只能是16位,这里不想维护两份所以就用16位长度的字符串作为密钥和iv偏移量* @returns */
function encryptAES(data, keyStr) {var encrypt = cryptoJs.AES.encrypt(data, cryptoJs.enc.Utf8.parse(keyStr), {iv: cryptoJs.enc.Utf8.parse(keyStr),mode: cryptoJs.mode.CBC,padding: cryptoJs.pad.Pkcs7}).toString();return encrypt;
}/*** AES解密* @param {String} data 带解密数据* @param {String} keyStr 同加密* @returns */
function decryptAES(data, keyStr) {var decrypt = cryptoJs.AES.decrypt(data, cryptoJs.enc.Utf8.parse(keyStr), {iv: cryptoJs.enc.Utf8.parse(keyStr),mode: cryptoJs.mode.CBC,padding: cryptoJs.pad.Pkcs7}).toString(cryptoJs.enc.Utf8);return decrypt;
}/*** * @returns 获得RSA的公钥,私钥*/
function getRsaKey() {const encrypt1 = new jsCrypto();return encrypt1.getKey();
}/*** RSA非对称加密 公钥加密 * @param {String} data 待加密数据 * @param {String} publicKey 公钥* @returns */
function encryptByPubKeyRSA(data, publicKey) {const encrypt1 = new jsCrypto();encrypt1.setPublicKey(publicKey)const res = encrypt1.encrypt(data)return res;
}/*** RSA非对称加密 私钥解密* @param {String} data 待解密数据* @param {String} privateKey 私钥匙* @returns */
function decryptByPrikeyRSA(data, privateKey) {const encrypt2 = new jsCrypto();encrypt2.setPrivateKey(privateKey)const res = encrypt2.decrypt(data);return res;
}/*** RSA非对称加密 私钥加密* @param {String} data 待加密数据* @param {String} privateKey 私钥* @returns */
function encryptByPriKeyRSA(data, privateKey) {const encrypt1 = new jsCrypto();encrypt1.setPrivateKey(privateKey)const res = encrypt1.decrypt(data)return res;
}/*** RSA非对称加密 公钥解密* @param {String} data 待解密数据* @param {String} publicKey 公钥* @returns */
function decryptByPubkeyRSA(data, publicKey) {const encrypt2 = new jsCrypto();encrypt2.setPublicKey(publicKey)const res = encrypt2.encrypt(data);return res;
}/*** 先用不可逆加密数据,再使用对称加密* @param {String} data 待sha+rsa加密数据* @param {String} rsaPubKey rsa公钥* @returns */
function encryptBySHA256AndRSA(data, rsaPubKey) {const shaStr = encryptSHA256(data);console.log("sha 不可逆加密后的密码:", shaStr)return encryptByPubKeyRSA(shaStr, rsaPubKey);
}/*** * @returns 返回一个promise对象 内包含该次请求的结果 data为被aes加密过的公钥字符串*/
async function getAesDescRsaPubKey() {return await axios.get('http://localhost:11111/yyx/security/rsaPubKey')
}export default {getRsaKey,getAesDescRsaPubKey, encryptByPubKeyRSA, decryptByPrikeyRSA, encryptByPriKeyRSA, decryptByPubkeyRSA, encryptSHA256, decryptAES, encryptAES, encryptBySHA256AndRSA
}

五,前端全局变量的存储

主要做了一件事,就是存储AES的密钥
创建一个js文件(下面的static可以自定义,在使用的时候调用清楚即可,该方式也可以导入函数到共有区域)

export default (app) => {console.log("加载公共属性到 $static 模块")app.config.globalProperties.$static = {RsaPubKey:"9c81aaf5-b408-49",}
}

在main.js中导入:

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from './router'
import global from './util/global'//导入const app = createApp(App)
app.use(ElementPlus)
app.use(router)
global(app)//使用
app.mount('#app')

调用的时候直接:this.$static.AESKey

六,前后端加密解密流程

后端接口两个: server.servlet.context-path: /yyx

  1. 前端调用查询AES加密的RSA公钥接口
@RestController
@RequestMapping("/security")
@Slf4j
public class SecurityController {@GetMapping("/rsaPubKey")public String getRsaPubKey() {log.info("client 获取 aes desc rsa pub key");return AESUtil.encrypt(SecurityConfig.getRsaPublicKey(), SecurityConfig.getAesKey());}}
  1. 前端调用注册接口
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {/*** ** @return*/@PostMapping("/register")public CommonResult<Boolean> register(@RequestBody UserDto userDto) {log.info("注册信息:{}", JSON.toJSONString(userDto));String password = userDto.getPassword();String pass = RSAUtil.decryptByPrivateKey(SecurityConfig.getRsaPrivateKey(), password);log.info("sha 加密的:{}", pass);return null;}public CommonResult<Boolean> login() {log.info("login");return null;}}

前端逻辑代码vue版本(初学前端)

<template><div><!-- 其他内容 --><h3>注册页</h3><form action="login" @submit.prevent="register"><label for="username">账户:</label><input type="text" id="username" v-model="username"><br><label for="pass">密码:</label><input type="password" id="pass" v-model="password"><button type="submit">注册</button></form></div>
</template><script>
import axios from "axios"
import crypto from "@/util/crypto";
export default {data() {return {username: "",password: ""}},methods: {register() {//demo版本 调用注册方法,请求后端得到aes加密后的rsa公钥crypto.getAesDescRsaPubKey().then((aesDescRsaPubKeyData) => {const aesDescRsaPubKey = aesDescRsaPubKeyData.data;console.log("aesDescRsaKey:", aesDescRsaPubKey)//对aes加密过的rsa公钥进行解密,得到rsa公钥const rsaPubKey = crypto.decryptAES(aesDescRsaPubKey, this.$static.AESKey);//对密码进行sha256+rsa加密const enCode = crypto.encryptBySHA256AndRSA(this.password, rsaPubKey);//真正调用后端的注册方法this.postRegister(this.username, enCode).then((data1) => {if (data1.status === 200) {this.$message({type: "success",message: "注册成功"});// 跳转this.$router.push("/index")}}).catch(() => {this.$message({type: "error",message: "注册失败"});})}).catch((error) => {this.$message({type: "error",message: "加密解密失败"});console.log(error)})},async postRegister(username, enCodePassword) {return await axios.post("http://localhost:11111/yyx/user/register",{username: username,password: enCodePassword})}}
};
</script>

七,前后端调试

前端记得 npm install 一下,安装一下需要的js库
前端模块给vue界面注册一个路由能展示即可(网上一大片教程)
前后端启动:
npm run dev
传入账号密码:
打控制台
在这里插入图片描述
后端收到:
在这里插入图片描述
一致,那么我们的加密解密流程就完成了

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

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

相关文章

Springboot+Vue项目-基于Java+MySQL的入校申报审批系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Python用KNN处理缺失值(4月30-5月1日)

首先试验KNN的简单示例代码 #方法3&#xff1a; # 本论文拟采用的填充缺失值的方法为KNN: import pandas as pd from sklearn.impute import KNNImputer #创建一个包含缺失值的数据集 data_KNN{第一列:[1,2,None,4,5],第二列:[3,None,5,7,9],第三列:[2,4,6,None,10] } dfpd.Da…

有哪些ai自动生成图片软件?AI绘画工具推荐

AI绘画工具是近年来快速发展的一种创新技术&#xff0c;它可以通过算法和机器学习技术来自动生成图片。那么又有有哪些ai自动生成图片软件呢&#xff1f;下面是小编给大家的AI绘画工具推荐。 一、爱制作AI 爱制作AI是一款多功能的人工智能助手&#xff0c;具备AI问答、AI写作、…

【FPGA】优化设计指南(一):设计原则

目录 避免采用不可综合的语句设计时采用同步的时钟组合逻辑与毛刺异步复位与同步复位动态分析与静态分析功能流水线时序违例乒乓操作面积和速度的平衡避免采用不可综合的语句 1.#1000延时语句 2.除法运算/,除非除数为2的整次幂 3.实数类型不可综合(real) 4.综上,使用可综合…

STM32进入睡眠模式的方法

#STM32进入睡眠模式的方法 今天学习了如何控制STM32进入睡眠模式&#xff0c;进入睡眠模式的好处就是省电&#xff0c;今天学习的只是浅度睡眠&#xff0c;通过中断就能唤醒。比如单片机在那一放&#xff0c;也许好几天好几个月都不用一次&#xff0c;整天的在那空跑while循环…

C#应用程序实现多屏显示

前言 随着业务发展&#xff0c;应用程序在一些特定场景下&#xff0c;只在一个显示器上展示信息已经不能满足用户需求。我们如何把主屏运行程序中多个窗体移动到各个扩展屏幕位置显示呢&#xff1f;C# 是通过什么方式来实现的&#xff0c;下面介绍 C# 使用 Screen 类的方式来实…

64、二分-搜索二维矩阵

思路&#xff1a; 通过使用二分方式&#xff0c;对于每行进行二分&#xff0c;因为每行的最后一个数小于下一行的第一个数&#xff0c;我们就可以依次二分。首先取出行数N&#xff0c;然后从0-N进行二分&#xff0c;如果mid最后一个数小于目标值说明0-mid中没有&#xff0c;舍弃…

jenkins转载文本

基于Docker容器DevOps应用方案 企业业务代码发布系统 一、企业业务代码发布方式 1.1 传统方式 以物理机或虚拟机为颗粒度部署部署环境比较复杂&#xff0c;需要有先进的自动化运维手段出现问题后重新部署成本大&#xff0c;一般采用集群方式部署部署后以静态方式展现 1.2 容…

鸿蒙开发接口Ability框架:【@ohos.ability.wantConstant (wantConstant)】

wantConstant wantConstant模块提供want中action和entity的权限列表的能力&#xff0c;包括系统公共事件宏&#xff0c;系统公共事件名称等。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导…

基于电磁激励原理利用视触觉传感器估计抓取力矩的方法

由于触觉感知能使机器人通过其触觉传递获取丰富的接触信息&#xff0c;触觉感知已经成为机器人机械臂的一种流行的感知方式。而在触觉传感器可获取的各种信息中&#xff0c;通过外界接触从抓取物体传递到机器人手指的力矩等信息&#xff0c;在完成各种指令的实现尤为重要。如图…

可重构柔性装配产线:AI边缘控制技术的崭新探索

在信息化和智能化浪潮的推动下&#xff0c;制造业正面临着前所未有的转型升级挑战。其中&#xff0c;可重构柔性装配产线以其独特的AI边缘控制技术&#xff0c;为制造业的智能化转型提供了新的解决方案。 可重构柔性装配产线是基于AI工业控制与决策平台打造的智能化生产系统。…

Spring Security介绍(三)过滤器(2)自定义

除了使用security自带的过滤器链&#xff0c;我们还可以自定义过滤器拦截器。 下面看下自定义的和security自带的执行顺序。 一、总结 1、自定义过滤器&#xff1a; 一般自定义fliter都是&#xff1a; import lombok.extern.slf4j.Slf4j; import org.springframework.ster…

QT - 创建Qt Widgets Application项目

在Qt中结合OpenGL使用&#xff0c;可以创建一个Qt Widgets应用程序项目。在创建项目时&#xff0c;您可以选择使用OpenGL模板来生成一个已经集成了OpenGL的项目。这个模板会自动帮助您集成OpenGL和Qt&#xff0c;并生成一个基本的OpenGL窗口。您可以在这个窗口中进行OpenGL的开…

闭嘴,如果你遇到偏执型人格!头脑风暴:王阳明心学向内求——早读(逆天打工人爬取热门微信文章解读)

看我极限头脑风暴 引言Python 代码第一篇 洞见 偏执型人格&#xff1a;跟谁在一起&#xff0c;谁痛苦第二篇 人民日报 来啦新闻早班车要闻社会政策 结尾 若天意未许晴好时&#xff0c; 勿将雨声作悲泣。 不向外界寻怨尤&#xff0c; 反求诸己养性灵。 引言 五一劳动节 第一天就…

C语言(操作符)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

区块链论文总结速读--CCF B会议 ICDCS 2023 共8篇

Conference&#xff1a;IEEE 43rd International Conference on Distributed Computing Systems (ICDCS) CCF level&#xff1a;CCF B Categories&#xff1a;Computer Architecture/Parallel and Distributed Computing/Storage Systems 计算机体系结构/并行与分布计算/存储…

【C语言】深入了解文件:简明指南

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、文件的概念1.1 文件名:1.2 程序文件和数据文件 二、数据文…

可靠的Mac照片恢复解决方案

当您在搜索引擎搜索中输入“Mac照片恢复”时&#xff0c;您将获得数以万计的结果。有很多Mac照片恢复解决方案声称他们可以在Mac OS下恢复丢失的照片。但是&#xff0c;并非互联网上的所有Mac照片恢复解决方案都可以解决您的照片丢失问题。而且您不应该花太多时间寻找可靠的Mac…

4月27日,上海Sui Meetup回顾与展望

活动吸引了超过200名报名者&#xff0c;其中的100多位技术爱好者亲临现场&#xff0c;一同见证了这一精彩时刻。 在这场为技术爱好者和开发者打造的盛会中&#xff0c;嘉宾们带来了内容丰富、见解独到的分享。 Sui 生态的活力与创新得到了充分展现。 在这场技术与创新的盛会…

74、堆-数组中的第K个最大元素

思路&#xff1a; 直接排序是可以的&#xff0c;但是时间复杂度不符合。可以使用优先队列&#xff0c;代码如下&#xff1a; class Solution {public int findKthLargest(int[] nums, int k) {if (numsnull||nums.length0||k<0||k>nums.length){return Integer.MAX_VAL…