当前位置: 首页 > news >正文

前后端加密传数据实现方案

前端加解密工具类(AES.js):

import CryptoJS from 'crypto-js';
//加密
export const aesEncrypt = (word, keyStr) => {keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345'; //判断是否存在ksy,不存在就用定义好的keyconst key = CryptoJS.enc.Utf8.parse(keyStr);const srcs = CryptoJS.enc.Utf8.parse(word);const encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });return encrypted.toString();
}/*** AES解密方法,兼容Java后端BASE64Encoder编码的加密字符串* @param {string} word - 需要解密的内容* @param {string} keyStr - 解密密钥,默认为'abcdsxyzhkj12345'* @returns {string} - 返回解密后的字符串*/
export const aesDecrypt = (word, keyStr) => {if (!word) {return '';}keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345';const key = CryptoJS.enc.Utf8.parse(keyStr);try {// 处理Java BASE64Encoder编码的字符串// 1. 确保BASE64字符串格式正确(替换可能的换行符和填充字符)let formattedWord = word.replace(/[\r\n]/g, '');// 2. 检查是否需要转换为CryptoJS可接受的BASE64格式// Java的BASE64Encoder可能会添加换行符和使用不同的填充字符if (formattedWord.indexOf('+') === -1 && formattedWord.indexOf('/') === -1) {// 如果不包含标准BASE64字符,可能需要转换formattedWord = formattedWord.replace(/-/g, '+').replace(/_/g, '/');}// 3. 确保BASE64字符串长度是4的倍数(添加必要的填充)while (formattedWord.length % 4 !== 0) {formattedWord += '=';}// 4. 尝试直接解密try {const decrypt = CryptoJS.AES.decrypt(formattedWord, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);if (decryptedStr && decryptedStr.length > 0) {return decryptedStr;}} catch (e) {console.log("直接解密失败,尝试其他方法", e);}// 5. 如果直接解密失败,尝试先解析BASE64try {const parsedWord = CryptoJS.enc.Base64.parse(formattedWord);const ciphertext = CryptoJS.lib.CipherParams.create({ciphertext: parsedWord});const decrypt = CryptoJS.AES.decrypt(ciphertext, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);if (decryptedStr && decryptedStr.length > 0) {return decryptedStr;}} catch (e) {console.log("BASE64解析后解密失败", e);}// 6. 尝试使用CryptoJS的格式try {const cipherParams = {ciphertext: CryptoJS.enc.Base64.parse(formattedWord)};const decrypt = CryptoJS.AES.decrypt(cipherParams,key,{mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return decrypt.toString(CryptoJS.enc.Utf8);} catch (e) {console.error("所有解密方法都失败", e);return '';}} catch (e) {console.error("AES解密错误:", e);return '';}
}//密钥(长度必须为16位,或者16位的倍数)
export const encodeSecret = "1936+=--ckl;P,gj"

前端调用方式:

引入AES.js
import { aesDecrypt,aesEncrypt,encodeSecret } from '/utils/AES';// 前端调接口传值前的加密
const data = {phone: formData.value.phonenumber,code: formData.value.captcha
};const new_data = aesEncrypt(JSON.stringify(data), encodeSecret);
const new_form ={body:new_data
}//解密的调用(后端对 res中的user对象进行了加密)
let user = aesDecrypt(res.user, encodeSecret)
console.log(user)

后端加解密工具类:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;public class AESUtil {private static final String cKey = "1936+=--ckl;P,gj"; // 这里Key长度必须为16位// 加密public static String encrypt(String sSrc) throws Exception {byte[] raw = cKey.getBytes("utf-8");SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"cipher.init(Cipher.ENCRYPT_MODE, skeySpec);byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。}// 解密public static String decrypt(String sSrc) throws Exception {try {byte[] raw = cKey.getBytes("utf-8");SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, skeySpec);byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);//先用base64解密try {byte[] original = cipher.doFinal(encrypted1);String originalString = new String(original, "utf-8");return originalString;} catch (Exception e) {System.out.println(e.toString());return null;}} catch (Exception ex) {System.out.println(ex.toString());return null;}}//    public static void main(String[] args) throws Exception {
//        /*
//         * 此处使用AES-128-ECB加密模式,key需要为16位。
//         */
//        // 需要加密的字串
//        String cSrc = "+nHGirm4nuxBebZu1ae4TQUxscfB0MzOJphHTyTwrhMsfWUNsfPzRzzdef1RPSM0pYVI17Vuk2TO9NoqPaWFQVqUDnSM1wahIGGBPR9uf3/C7/AgT40qGSlKO1H1sYQrztcT5Ev4BMeMJfZfVGUUMcdxtShXxGqomJfXC1m783Df1jtZD8DEndltsc6CCDejktm3XKyGrdLtev4atG5k3dUi2AwRI7wbj8G4unWH9lCxCVLj/Wny+lzMYFZvq3MV5lg4wnzVdUjG/q1KdT2QmLSyuGdKd3+s33brLJHn50q6ymD8y1IEo3bTNdjsj8TMNZ0Aabb8MaJ2bt/pvPZsG22Os95jYDiMaM4AOMT4KuD5G9PX2aATNx8CU1xVZ7/OVcyCxiGxd/N7nXnJ/651ggmH2vuCGyYXRMVKOIZYdYfrSJqPIqnRR5xXpRgBm7IsAfEFwxrSRc0EKBTbZE+BB9o793bTgJCpNlBVzdmx+W3mrJWapYBEJd6oRVNR7hm8PRSIZEnH2o2FPA3JBedsJjh0M/QolXleSo7KYHlm/1M=";
//        System.out.println(cSrc);
//        // 加密
//        String enString = AESUtil.Encrypt(cSrc, cKey);
//        System.out.println("加密后的字串是:" + enString);
//        // 解密
//        String DeString = AESUtil.decrypt(cSrc);
//        System.out.println("解密后的字串是:" + DeString);
//    }}

后端调用加解密方式:

@ResponseBody
@PostMapping("/login")
public AjaxResult login(@RequestBody String body)
{AppUserLoginReq req = null;try {JSONObject bodyJOSN = JSON.parseObject(body);String decrypt = AESUtil.decrypt(bodyJOSN.getString("body"));req = JSON.parseObject(decrypt, AppUserLoginReq.class);// req即解密出来的对象(这里是针对前端传加密后的值对应body)// 这里省略了一些逻辑。。。。String token = loginService.appLogin(sysUser.getUserName());AjaxResult ajax = AjaxResult.success("登录成功");SysUser sysUser = userService.selectUserByPhone(req.getPhonenumber());// 这里相当于在前端返回的数据中对 res.user做了加密ajax.put("user", AESUtil.encrypt(JSON.toJSONString(sysUser)));return ajax;} catch (Exception e){return AjaxResult.error("参数异常");}
}

http://www.dtcms.com/a/319071.html

相关文章:

  • 强反光干扰下读数误差↓79%!陌讯多模态算法在仪表盘识别场景的落地优化​
  • LINUX-文件查看技巧,重定向以及内容追加,man及echo的使用
  • 迅为RK3588开发板Android proc文件系统查询-内核版本查询
  • PyTorch RNN 名字分类器
  • 11-netty基础-手写rpc-支持多序列化协议-03
  • 【MySQL基础篇】:MySQL事务并发控制原理-MVCC机制解析
  • qt的元对象系统详解
  • 2深度学习Pytorch-神经网络--全连接神经网络、数据准备(构建数据类Dataset、TensorDataset 和数据加载器DataLoader)
  • Activiti 中各种 startProcessInstance 接口之间的区别
  • [激光原理与应用-169]:测量仪器 - 皮秒激光器研发过程中所需要的测量仪器
  • 2025年机械工程与自动化技术国际会议(ICMEAT 2025)
  • 力扣 hot100 Day68
  • 主流小程序 SaaS 平台测评,2025年小程序开发避坑指南
  • 移动端录屏需求调研:以小熊录屏为例的轻量级实现方案
  • .NET9 AOT完全自举了吗?
  • 面向对象之类方法,成员变量和局部变量
  • 【前端八股文面试题】JavaScript中的数据类型?存储上的差别?
  • react_05create-react-app脚手架详细解析(export)
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的微商产品经营策略研究
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的用户留存策略研究
  • iOS 文件管理实战指南,用户文件、安全访问与开发调试方案
  • Socket 编程预备
  • 拥抱云原生:从传统架构到云原生架构的演进与实践
  • 算法题(182):滑动窗口
  • mysql基础-分组查询
  • 全面解析 URL 重定向原理:从协议、实现到安全实践
  • 【物联网】基于树莓派的物联网开发【24】——树莓派安装influxDB时序数据库
  • 套接字编程UDP
  • Android-Kotlin基础(Jetpack③-LiveData)
  • 数据结构初阶(4)栈