站长资讯网
最全最丰富的资讯网站

前端Crypto.jsAES加密,PHP openssl_decrypt()解密进行数据安全传输

前几日做微信小程序开发,对于前后端分离的项目,如果涉及到的敏感数据比较多,我们一般采用前后端进行接口加密处理,采用的是 AES + BASE64 算法加密,前端使用纯JavaScript的加密算法类库crypto-js进行数据加密,后端使用PHP openssl_decrypt()解密进行数据安全传输~

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:

前端Crypto.jsAES加密,PHP openssl_decrypt()解密进行数据安全传输

crypto-js(GitHub)是谷歌开发的一个纯JavaScript的加密算法类库,可以非常方便的在前端进行其所支持的加解密操作。目前crypto-js已支持的算法有:MD5,SHA-1,SHA-256,AES,Rabbit,MARC4,HMAC,HMAC-MD5,HMAC-SHA1,HMAC-SHA256,PBKDF2。常用的加密方式有MD5和AES。

crypto-js 安装方式

  npm install crypto-js

安装成功以后直接找到crypto-js.js文件,并将其引入 const CryptoJS = require('./crypto-js.js');

uniapp app开发 前后端分离 api接口安全策略

1. 请求服务端获取随机token, create_time并存到文件缓存中

2. 前端拿到token,create_time使用CryptoJS加密生成签名,放到请求头中

3. 服务端工程师解密,完成sign时效性校验 通过后获取接口数据

    const CryptoJS = require('./crypto-js.js'); //引用AES源码js     const BASE_URL = "http://love.ouyangke.net/"     const key = CryptoJS.enc.Utf8.parse("chloefuckityoall"); //十六位十六进制数作为密钥     const iv = CryptoJS.enc.Utf8.parse('9311019310287172'); //十六位十六进制数作为非空的初始化向量       export const getAccessToken = ()=> {  	uni.request({ 		url: BASE_URL + 'getAccessToken', 		method: 'GET', 		success:   (res) => { 			// console.log(res); 			const { 				data 			} = res  			 			if (data.code == 0) { 				return 			} 			// console.log(data.token); 			var encrypted = CryptoJS.AES.encrypt(JSON.stringify({ 				token: data.token, 				create_time: data.create_time 			}), key, { 				mode: CryptoJS.mode.CBC,  				padding: CryptoJS.pad.Pkcs7, 				iv: iv 			}).toString() 			// console.log('签名完成',encrypted ); 			// 记录在本地 			  uni.setStorage({ 				key:"sign", 				data:encrypted 			}); 	  			  			   			 		}, 		fail: (err) => { 			console.log(JSON.stringify(err)); 		} 	 })     }

接着将封装的getAccessToken函数注册到vue原型上

前端Crypto.jsAES加密,PHP openssl_decrypt()解密进行数据安全传输

然后在需要使用的方法中直接调用该方法就可以了,如图:

前端Crypto.jsAES加密,PHP openssl_decrypt()解密进行数据安全传输

后端tp6创建中间控制器Common.php,让所有除了生成token的控制器集成这个中间控制器,实时检测签名的有效性

common.php代码如下:

 <?php     namespace applovecontroller;     use appBaseController;     use thinkfacadeCache;     use libApiAuth;     class Common extends BaseController     {                      const ILLEGAL_SIGN = 'sign is illegal';         public function initialize()         {                             $this->checkRequestAuth();             }              //验证方法          /**     	 * 检验sign的真实性      	 * @return bool  校验通过返回true,失败返回false     	 *           * 检查app每一次提交的数据是否合法          */         public function checkRequestAuth()         {              //获取header头的某个信息sign             $sign = request()->header('sign');                          $res = ApiAuth::checkSign($sign);                           if(!$res)             {                 echo json_encode(['status'=>0,'msg'=>self::ILLEGAL_SIGN]);                 exit;             }                       }     	      	                       }

ApiAuth.php

<?php namespace lib; use thinkfacadeCache; //校验类   class ApiAuth {     // 生成签名     public static function setSign(Array $data=[])     {         ksort($data);         $sign_str = http_build_query($data);         return (new Aes())->encrypt($sign_str);     }               // 校验sign          public static function checkSign($sign)     {            //   解密sign 获取到的明文信息          $str = (new Aes())->decrypt($sign);                   if(!$str)         {             return false;         }                  $arr = json_decode($str,true);              $res =  Cache::get($arr['token']);                     if(!is_array($arr) || count($arr)!=2 || !$res)         {                           return false;         }                  if($res)         {             if($arr['create_time'] != $res)             {                                  return false;             }else{                 //校验sign有效期                  $cliff = time()-$arr['create_time'];                                  if ( $cliff > config('app.aes.api_sign_expire_time')) {                                        return false;                   }                                  //验证通过,删除token                 Cache::delete($arr['token']);                 return true;             }         }                 } }

Aes.php:

<?php namespace lib; class Aes{     private $key = null;     private $iv = null;          public function __construct(){         $this->iv = config('app.aes.aesiv');//这里是从配置文件中取和前端一致的iv与key         $this->key = config('app.aes.aeskey');     }               public function encrypt($plainText)     {         $data = openssl_encrypt($plainText, 'AES-128-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);         $data = base64_encode($data);         return $data;     }          public function decrypt($cipher)     {         $plainText = openssl_decrypt(base64_decode($cipher),'AES-128-CBC',$this->key,OPENSSL_RAW_DATA,$this->iv);                        return $plainText;     }       }

将配置信息部署配置在这里

前端Crypto.jsAES加密,PHP openssl_decrypt()解密进行数据安全传输

【推荐学习:javascript高级教程】

赞(0)
分享到: 更多 (0)