很多时候我们的接口都是请求和响应参数都是明文显示的话就会导致有些恶意用户伪造请求参数尽量批量请求,这样会导致我们的程序数据异常并且可能会增加服务器负载,所以我们需要使用加密的参数进行前后端的数据互通常见的就是AES加密方案。
AES加密技术
AES加密,即高级加密标准(Advanced Encryption Standard),是一种广泛应用的对称加密算法。它具有以下几个显著特点:
- 高安全性:AES是一种被广泛认可的安全加密标准,由美国国家标准与技术研究院(NIST)于2001年正式采纳。它已经经受了多年的各种密码分析的挑战,至今没有被证实存在有效的攻击方式。
- 密钥长度灵活:AES支持多种密钥长度,包括128位、192位和256位,这为不同的安全需求提供了灵活性。较长的密钥通常意味着更高的安全性,但也意味着更高的计算成本。
- 操作简单:AES的算法结构相对简单,易于实现和集成到各种应用程序中。对称密钥的特性意味着加密和解密过程使用相同的密钥,简化了密钥管理和分发的过程。
下面我用thinkphp 实现使用AES进行加密和解密并进行前后端传递。
这是加密和解密的函数 可以放到tp的 common.php 文件或你所用的控制器的文件以待使用。
/**
* 加密字符串
* @param string $data 字符串
* @param string $key 加密key
* @param string $iv 加密向量
* @return string
*/
function encrypt($data, $key, $iv)
{
//支持php5
//$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
//支持php8
//$decrypted = openssl_encrypt($data, 'AES-128-CBC', $key,2, $iv);
$encrypted = openssl_encrypt($data, "AES-128-CBC", $key, true, $iv);
return base64_encode($encrypted);
}
/**
* 解密字符串
* @param string $data 字符串
* @param string $key 加密key
* @param string $iv 加密向量
* @return string
*/
function decrypt($data, $key, $iv)
{
//支持php5
//$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC, $iv);
//支持php8
//$decrypted = openssl_decrypt($data, 'AES-128-CBC', $key,2, $iv);
$decrypted = openssl_decrypt($data, 'AES-128-CBC', $key, 0, $iv);
return $decrypted;
}
首先要设置key 和 vi 都需要16位的字符 必须16位 也可以vi由后端随机生成在给前端返回是携带vi参数再由前端根据你传的vi值进行解密。
$iv = "IVIVIV_LUYILAFEI";
$encrypt_key = "XDXDXU_LUYILAFEI";
//请换成你自定义的
//解密调用 $data = 前端发送给来的加密后的base64字符串
$params = decrypt($data, $encrypt_key, $iv);
//这样就能获取到解密后的数据信息 如果是json则需要转码
$params = json_decode($params, true);
//这里是加密的示例
$encrypt_data = json_encode([
'token' => 'xxxxx',
'user_id' => 2000,
'time' => time(),
'r' => date('YmdHis')
]);
$encrypted = encrypt($encrypt_data, $encrypt_key, $iv);
//返回一个base64的字符串发送给前端
前端我们要先安装 crypto-js
npm install crypto-js --save
安装好之后我们在项目中新建一个文件用于存放加密和解密的函数库
如 ase.js
var CryptoJS = require("crypto-js");
let crypt_key = 'IVIVIV_LUYILAFEI';
let crypt_iv = 'XDXDXU_LUYILAFEI';
// 加密
export function encrypt(data) {
// 将key解析为字节
let aes_key = CryptoJS.enc.Utf8.parse(crypt_key);
// 将iv解析为字节
let new_iv = CryptoJS.enc.Utf8.parse(crypt_iv);
// AES加密 CBC模式 ZeroPadding
let encrypted = CryptoJS.AES.encrypt(data, aes_key, {
iv: new_iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 返回字符串
return encrypted.toString();
}
//解密
export function decrypt(data) {
let aes_key = CryptoJS.enc.Utf8.parse(crypt_key);
let aes_iv = CryptoJS.enc.Utf8.parse(crypt_iv);
// 将数据编码成Base64格式
let baseResult = CryptoJS.enc.Base64.parse(data);
let ciphertext = CryptoJS.enc.Base64.stringify(baseResult);
// AES解密 CBC模式 ZeroPadding
let decryptResult = CryptoJS.AES.decrypt(ciphertext, aes_key, {
iv: aes_iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 返回字符串
let resData = decryptResult.toString(CryptoJS.enc.Utf8).toString();
return resData;
}
在我们需要用到加密和解密的文件引入 之前创建的js文件 并进行函数调用
import {
encrypt,
decrypt
} from "@/libs/js/aes.js"
//调用解密函数 直接传入后端返回的base64字符串即可
let decrypted_string = decrypt(decrypt_string);
//如果是json请 JSON.parse(decrypted_string)
//加密的话也是一样调用函数对象需转换json
let data_params = {
id: this.id,
...this.datas
};
let data_str = JSON.stringify(data_params);
let skey_string = encrypt(data_str);
//下面是发送请求示例
uni.$u.http.post('/api/index/text', {
//请求参数
data: skey_string
}, {
custom: {
auth: true,
loading: true,
codes: true
}
}).then(res => {
if (res.code == 1) {
uni.$u.toast(res.msg);
} else {
uni.$u.toast(res.msg);
}
}).catch(() => {
uni.$u.toast('error');
})
//即可获取到加密的base64字符串 发送给后端请求 后端再进行解密即可
上面的示例符合单独调用使用如果是想要全局使用也可以在请求的拦截器上面进行使用。
简单的示例适合小白使用,写好之后在aes.js 做一下混淆加密 可以百度一下js混淆工具 有很多,虽然可以前端混淆但是在技术能力比较出众的人面前前端的任何加密都是不存在的所以如果想做到我们写的程序做到万无一失还是要在后端层面多做安全措施,在整体的安全策略中综合考虑前端和后端的完美加密解决方案。