项目场景:

领导要求公司后台的全部接口与前端交互时,所有参数以及返回值需要进行加密。后端语言 PHP,使用框架 tp5.1,前端vus.js,使用CryptoJS加解密


效果如下:

前端传参:

后端返回:

前端代码:

前端使用CryptoJS来加密。说明:为了数据安全性,前端需要额外传递一个参数sign给到后端,后端按前端的sign生成规则重新生成一个sign并与前端传递的sign进行对比校验,前端的sign生成代码如下:

function objKeySort(obj) { //排序的函数// obj:原始的请求参数对象// obj:{"username":"111111","password":"123456","terminal":"PC"};var word_key =Object.assign({},obj)// console.log('cd='+JSON.stringify(obj))var newkey = Object.keys(word_key).sort();//先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组var newObj = {}; //创建一个新的对象,用于存放排好序的键值对for (var i = 0; i < newkey.length; i++) { //遍历newkey数组newObj[newkey[i]] = obj[newkey[i]]; //向新创建的对象中按照排好的顺序依次增加键值对}var str = '';for (var key in newObj) {// if (newObj[key]===undefined) {//     newObj[key] = '';// }if(typeof newObj[key]!='object'&& typeof newObj[key]!='boolean'&& typeof newObj[key]!='undefined' ){str += `${key}=${newObj[key]}&`;}}str = str.substr(0, str.length - 1);str+='&'+key_str+'&'+iv_str;// console.log(str)var md5_str = md5(str);return md5_str; //返回排好序的新对象
}

说明:前后端的签名sign在生成时,前端的参数包含数组、对象、bool值时,这些值后端接收的值与前端会不一致,导致验证签名失败,所以前端在生成sign时,过滤掉数组、对象以及bool值。


let str = {"username":"111111","password":"123456","terminal":"PC","sign":"前面生成的sign"};
let srcs = CryptoJS.enc.Utf8.parse(JSON.stringify(str));
var encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7
});
var res = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
// 注意,这里最后使用了base64加密,不用的话,后端无法正确解密。
console.log( res );
// d99HVdbHhtW1HAsD53hYSjPcSB5pN4fDpXzJHpBY2gw0MBOq8rPZFKDKyOkOccBWOZjFwE9Mqe2TUNDEn6Vk9Q==

前端解密代码:

//解密
key = CryptoJS.enc.Utf8.parse("1572329129539WZH");//十六位十六进制数作为密钥,可自行设置
iv = CryptoJS.enc.Utf8.parse("ZZWBKJ_ZHIHUAWEI");//十六位十六进制数作为密钥偏移量,可自行设置
let str = "d99HVdbHhtW1HAsD53hYSjPcSB5pN4fDpXzJHpBY2gw0MBOq8rPZFKDKyOkOccBWOZjFwE9Mqe2TUNDEn6Vk9Q=="; // 前面加密生成的数据
var decrypted = CryptoJS.AES.decrypt(str, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7
});
let res = JSON.parse(CryptoJS.enc.Utf8.stringify(decrypted));
console.log(res);

### 后端代码:

后端加密解密放在中间件里面实现
加密代码如下:

namespace app\http\middleware;
use think\Response;
class Encrypt
{/***  加密中间件*/public function handle($request, \Closure $next){$response = $next($request);$content = $response->getContent();$content = json_decode($content,true);$data = $content['data'] ?? [];if (!empty($data)) {// 添加中间件执行代码$mini_secret = '1572329129539WZH';$mini_iv = 'ZZWBKJ_ZHIHUAWEI';$str = json_encode($data);$mini_sign = openssl_encrypt($str, 'AES-128-CBC',$mini_secret,0, $mini_iv);$content['data'] = ['result' => $mini_sign];$response->content(json_encode($content));}return $response;}
}

解密代码如下:

namespace app\http\middleware;
use app\common\exception\JsonException;
use app\common\enums\ErrorCode;
use think\facade\Response;
use think\Request;
class Decrypt
{/***  解密中间件*/public function handle($request, \Closure $next){// 这里是解决跨域问题if(!$request->isCli()){header('Access-Control-Allow-Origin:*');header('Access-Control-Allow-Methods:GET,POST,PUT,DELETE,PATCH,OPTIONS');header('Access-Control-Allow-Headers:Content-Type, X-ELEME-USERID, X-Eleme-RequestID, X-Shard,X-Shard, X-Eleme-RequestID,X-Companyid,X-Adminid,X-Token');}if ($request->isOptions()){return Response::create()->send();die();}// 添加中间件执行代码$mini_sign = $request->param('mini_sign'); // 前端传的加密后的参数if (!empty($mini_sign)) {// 参数解密// 获取加密密钥和向量(跟前端保持一致,可写在配置里)$mini_secret = '1572329129539WZH';$mini_iv = 'ZZWBKJ_ZHIHUAWEI';//2:通过request获取前端传入的 $mini_sign数据$mini_sign = str_replace(' ','+',$mini_sign);//3:对$str_one数据进行解密$str = openssl_decrypt($mini_sign, 'AES-128-CBC',$mini_secret,0, $mini_iv);//4:对解密后的数据进行 json_decode() 处理$arr_one = json_decode($str, JSON_UNESCAPED_UNICODE);//5:获取签名 sign$sign = $arr_one['sign'];//6:去除$arr_one数组中的sign键值对unset($arr_one['sign']);$signData = $arr_one;//7:对数组$arr_one,依据键值,做升序排序(去掉数组,对象)foreach ($signData as $key => $val) {if (is_array($val) || is_object($val) || is_bool($val)) {unset($signData[$key]);}}ksort($signData);//8:对排序后的数组 $arr_one,构造成字符串$str_one,构建的字符串格式类似于 A=a&B=b&C=c$str_one = http_build_query($signData);//9:构建字符串$str_two = $str_one . '&'. $mini_secret . '&' .$mini_iv;$str_two = urldecode($str_two);//10:生成验证签名字符串 $check_sign$check_sign = md5($str_two);//11:判断 $sign 是否与 $check_sign 相同;if ($check_sign != $sign) {throw new JsonException(ErrorCode::VALIDATION_FAILED, "签名不合法。");}// 这里将原始的请求参数加到请求对象里面去,这样控制器里面通过request对象就可以拿到对应参数if ($request->isGet()) {$request->withGet($arr_one);}if ($request->isPost()) {$request->withPost($arr_one);}// 这里的代码是为了解决,部分控制器使用request()->param()方法获取不到参数的问题foreach ($arr_one as $key => $val) {$request->__set($key,$val);}}return $next($request);}
}

结束

php后端aes加密前端解密相关推荐

  1. java和js实现前端加密后端解密,后端加密前端解密(Base64)

    目录 1.前端加密后端解密 2.后端加密前端解密 在前端和后端数据传输时,常常涉及到隐私数据的传输(例如用户名和密码),这时,我们就需要对隐私数据进行加密解密 1.前端加密后端解密 1.1 前端jqu ...

  2. 探讨.NET Core中实现AES加密和解密以及.NET Core为我们提供了什么方便!

    前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...

  3. Java中的AES加密和解密(CBC模式)

    通过有线方式传输诸如纯文本密码之类的机密数据总是容易受到安全性的影响,始终建议对此类信息进行加密并使用SSL传输这些机密数据.Java为此提供了多种加密算法.在本文中,我们将讨论Java中具有CBC模 ...

  4. Oracle的AES加密与解密用法

    Oracle的AES加密与解密用法 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/it ...

  5. python实现字母的加密和解密 字典_python实现AES加密与解密

    AES加密方式有五种:ECB, CBC, CTR, CFB, OFB 从安全性角度推荐CBC加密方法,本文介绍了CBC,ECB两种加密方法的python实现 python 在 Windows下使用AE ...

  6. aes加密算法python实现_Python基于pycrypto实现的AES加密和解密算法示例

    本文实例讲述了Python基于pycrypto实现的AES加密和解密算法.分享给大家供大家参考,具体如下: 一 代码 # -*- coding: UTF-8 -*- import string imp ...

  7. oracle实现aes解密_Oracle的AES加密与解密用法

    Oracle的AES加密与解密用法 2013年12月11日 11:50:35 iteye_751 阅读数:428 --加密字符串 create or replace function des3_enc ...

  8. Php AES加密、解密与Java互操作的问题

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  9. 每日一课 | AES加密和解密(CBC模式)

    通过有线方式传输诸如纯文本密码之类的机密数据总是容易受到安全性的影响,始终建议对此类信息进行加密并使用SSL传输这些机密数据.Java为此提供了多种加密算法.在本文中,我们将讨论Java中具有CBC模 ...

最新文章

  1. 2022-2028年中国PET薄膜行业市场深度分析及未来趋势预测报告
  2. 华为服务器显示红色的心跳,服务器心跳检查
  3. scrum与第一次teamwork
  4. 如何写出更好的代码(文末有福利)
  5. mysql cmmand not found
  6. 微信公众号-注册最全6种类型接口权限,注册哪个好?
  7. [渝粤教育] 中国地质大学 职业健康管理体系 复习题
  8. php电竞酒店系统,电竞酒店系统管理@电竞酒店云管家@电竞酒店解决方案
  9. 【项目实践】充电台灯电路拆解
  10. java 坐标反算_Java实现坐标反算方位角
  11. Luogu3307:[SDOI2013]项链
  12. 理解SaaS、PaaS、LaaS以及之间的区别
  13. 单反相机的传奇—佳能单反50年辉煌之路(连载十六)
  14. 使用Mozilla Thunderbird 创建ics日历文件
  15. opencv学习-高斯金字塔和拉普拉斯金字塔
  16. 【Github】使用github
  17. 瞧瞧你的指甲,看你身体还好不!
  18. 6a标准 api_API6A标识规范(最新)
  19. 高中新课程作业本 数学 必修1 答案
  20. 域名注册-服务器备案

热门文章

  1. 计算机excel按F4是那个公式,excel中键盘F4到底怎么用?_excle 中的f4
  2. error LNK2005:
  3. idea配置springboot
  4. Python中 ‘\r‘ 的实际应用
  5. R or Python,到底学哪个?这篇文章来告诉你......
  6. 区块链技术之P2P网络(二)
  7. LeetCode 最长公共子串
  8. pytorch之torch.nn.Conv2d()函数详解
  9. 第三代电子计算机的核心部件为,计算机基础试题
  10. perlembed - 在 C 程序中嵌入 perl