前后端数据加密代码实战(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.hqwc.cn/news/661200.html

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

相关文章

OpenCV 实现霍夫圆变换(52)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV实现霍夫变换(51) 下一篇:OpenCV 实现重新映射(50) 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 HoughCircles()检测图像中的圆圈。 理论 Hough 圆…

KPlayer搭建指南:开启24小时直播之旅

引言 在这个数字化时代&#xff0c;无人值守直播成为了一种新兴的趋势。无论是企业还是个人&#xff0c;都可以通过无人值守直播来提高效率和观众参与度。本文将介绍如何使用KPlayer在Linux环境下搭建无人值守直播系统。 KPlayer简介 KPlayer是一款基于Linux的媒体服务器工具…

STM32利用硬件I2C读取MPU6050陀螺仪数据

有了前面的基本配置&#xff0c;这节读取MPU6050的数据还算是简单&#xff0c;主要就是初始化时给MPU6050一些配置&#xff0c;取消睡眠模式&#xff0c;MPU6050开机是默认睡眠模式的&#xff0c;读写无效&#xff0c;所以上来就要先更改配置&#xff1a; MPU6050寄存器初始化…

实操——使用uploadify插件(php版和Java版) 与 Dropzone.js插件分别实现附件上传

实操——使用uploadify插件&#xff08;php版和Java版&#xff09;与 Dropzone.js插件分别实现附件上传 1. 使用uploadify插件上传1.1 简介1.1.1 简介1.1.2 参考GitHub 1.2 后端PHP版本的uploadify1.2.1 下载项目的目录结构1.2.2 测试看界面效果1.2.3 附页面代码 和 PHP代码 1.…

面试经典算法题之双指针专题

力扣经典面试题之双指针 ( 每天更新, 每天一题 ) 文章目录 力扣经典面试题之双指针 ( 每天更新, 每天一题 )验证回文串收获 392. 判断子序列 验证回文串 思路 一: 筛选 双指针验证 class Solution { public:bool isPalindrome(string s) {// 所有大写字母 > 小写 去除非字母…

Floyd判圈算法

目录 1.概念以及用途 2.具体解决代码以及逻辑推理 &#xff08;1&#xff09;判断链表是否有环 &#xff08;2&#xff09;判断环的长度 &#xff08;3&#xff09;判断环的起始点 3.例题 1.概念以及用途 Floyd判圈算法&#xff0c;又被称之为龟兔赛跑算法&#xff08;为…

【stomp 实战】Spring websocket 用户订阅和会话的管理源码分析

通过Spring websocket 用户校验和业务会话绑定我们学会了如何将业务会话绑定到spring websocket会话上。通过这一节&#xff0c;我们来分析一下会话和订阅的实现 用户会话的数据结构 SessionInfo 用户会话 用户会话定义如下&#xff1a; private static final class Sessio…

Linux内核深入学习 - 中断与异常(上)

中断与异常 中断通常被定义为一个事件&#xff1a;让事件改变处理器执行的指令顺序这样的事件&#xff0c;与CPU芯片内外部硬件电路产生的电信号相对应&#xff01; 中断通常分为同步中断与异步中断&#xff1a; 同步中断指的是当指令执行时&#xff0c;由CPU控制单元产生的…

《QT实用小工具·四十九》QT开发的轮播图

1、概述 源码放在文章末尾 该项目实现了界面轮播图的效果&#xff0c;包含如下特点&#xff1a; 左右轮播 鼠标悬浮切换&#xff0c;无需点击 自动定时轮播 自动裁剪和缩放不同尺寸图片 任意添加、插入、删除 单击事件&#xff0c;支持索引和自定义文本 界面美观&#xff0c;圆…

【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【MyBatis】 MyBatis框架下的高效数据操作&#xff1a;深入理解增删查改&#xff08;CRUD&#xff09; &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 My …

树的中心 树形dp

#include<bits/stdc.h> using namespace std; int n; const int N 100005; // 无向边 int ne[N * 2], e[N * 2], idx; int h[N]; int vis[N];int ans 0x7fffffff;void add(int a, int b) {e[idx] b, ne[idx] h[a], h[a] idx; }int dfs(int u) { // 作为根节点vis[u]…

HotSpot VM概述

许多技术人员只把JVM当成黑盒&#xff0c;要想改善Java应用的性能和扩展性无疑是一项艰巨的任务。若要提高Java性能调优的能力&#xff0c;就必须对现代JVM有一定的认知。 HotSpot VM是JDK 1.3版本之后默认的虚拟机&#xff0c;目前是使用最广泛的Java虚拟机。本文主要介绍HotS…