数据安全解决方案:AES 加密

1. 数据安全介绍;

加密方式:
MD5
AES:对称的加密算法(还有 DES,3DES 等)。对称加密算法的底层机制会不一样。AES 有更高的速度和资源使用率,比其它的对称算法要高。
RSA:非对称的加密算法,效率稍差,数据量大的时候加密时间较长,一般用于小数据加密
加密步骤:
header 当中放一些基础的参数,比如 sign(加密字符串),version(版本号),app_type,did(设备号),model(机型)
每次 http 请求都携带验签 sign
sign 唯一性保证
请求参数、返回数据按安全性适当加密
access_token
附:RESTful api 中 HTTP 状态码
200:请求成功
201:创建成功
202:更新成功
400:无效请求
401:未授权
403:禁止访问
404:请求资源不存在
500:内部错误

2. 授权码 sign 解析;

重点:
AES加密解密算法的使用
sign 算法生成
实例:
环境:PHP7 + Thinkphp5
  • 配置文件:新增 config/aes.php
<?php

return [
    'password_pre_halt' => '_#sing_ty',	// 密码加密盐
    'aeskey' => 'sgg45747ss223455'		// aes 密钥, 服务端和客户端必须保持一致
];
  • AES 加密类库:新建 application/lib/common/Aes.php
<?php
namespace app\common\lib;

/**
 * AES 加密、解密类库(适用于 PHP 7)
 * Class Aes
 * @package app\common\lib
 */
class Aes {

    private $key = null;

    /**
     *
     * @param $key 		密钥
     * @return String
     */
    public function __construct() {
        // AES 加解密密钥,服务端和客户端保持一致
        $this->key = config('aes.aeskey');;
    }

    /**
     * @param $string 需要加密的字符串
     * @return string
     */
    public function encrypt($string){
        // openssl_encrypt 加密不同于 mcrypt,对秘钥长度要求,超出16位加密结果不变
        $data = openssl_encrypt($string, 'AES-128-ECB', $this->key, OPENSSL_RAW_DATA);

        // $data = bin2hex($data);
        $data = base64_encode($data);

        return $data;
    }


    /**
     * @param $string 需要解密的字符串
     * @return string
     */
    public function decrypt($string){
        // $string = hex2bin($string);
        $string = base64_decode($string);
        $decrypted = openssl_decrypt($string, 'AES-128-ECB', $this->key, OPENSSL_RAW_DATA);

        return $decrypted;
    }

}
  • 新建:application/lib/common/Iauth.php
<?php
namespace app\common\lib;
use app\common\lib\Aes;

/**
 * Class IAuth
 */

class IAuth {

    /**
     * 生成每次请求的 sign
     * @param array $data
     * @return string
     */
    public static function setSign($data = []) {
        // 以下步骤和客户端保持一致
        // 按字段排序
        ksort($data);
        // 字符串以"&"进行拼接
        $string = http_build_query($data);
        // 通过 AES 来加密
        $string = (new Aes())->encrypt($string);

        return $string;
    }
}
  • 新建:application/api/controller/Common.php
<?php
namespace app\api\controller;

use app\common\lib\Aes;
use app\common\lib\Iauth;

/**
 * API 模块公共控制器
 * Class Common
 * @package app\api\controller
 */
class Common{
    /**
     * 测试
     */
    public function testAes(){
		// 生成 sign:
        $data = [
            'did' => '12345dg',
            'version' => 1
        ];
        // echo Iauth::setSign($data);exit;
        
        // 输出加密 sign:
        $str = 'sRCvj52mZ8G+u2OdHYwmysvczmCw+RrAYWiEaXFI/5A=';
        echo (new Aes())->decrypt($str);exit;
        // 输出;did=12345dg&version=1
    }

}
  • 访问:http://192.168.2.214/tp5/public/index.php/api/common/testAes

3. sign 检验。

  • 修改:application/lib/common/Iauth.php
<?php
namespace app\common\lib;
use app\common\lib\Aes;
use think\Cache;

/**
 * Class IAuth
 */

class IAuth {

    /**
     * 生成每次请求的 sign
     * @param array $data
     * @return string
     */
    public static function setSign($data = []) {
        // 以下步骤和客户端保持一致
        // 按字段排序
        ksort($data);
        // 字符串以"&"进行拼接
        $string = http_build_query($data);
        // 通过 AES 来加密
        $string = (new Aes())->encrypt($string);

        return $string;
    }

	/**
	 * 新增方法
     * 检查 sign 是否正常
     * @param array $data
     * @param $data
     * @return boolen
     */
    public static function checkSignPass($data) {
        $str = (new Aes())->decrypt($data['sign']);

        if(empty($str)) {
            return false;
        }

        // 解密后格式:did=12345dg&version=1
        parse_str($str, $arr);
        if(!is_array($arr) || empty($arr['did']) || $arr['did'] != $data['did']) {
            return false;
        }
        
        if(!config('app_debug')) {
        	// 使用 13 位时间戳,数据重复概率小
        	// 超过 10 秒为非法请求
        	// 建议存在 redis
            if ((time() - ceil($arr['time'] / 1000)) > 10) {
                return false;
            }

            // 唯一性判定,第二次被请求无法使用
            if (Cache::get($data['sign'])) {
                return false;
            }
        }
        return true;
    }

}
  • 附:13位时间戳生成
function get13TimeStamp() {
    list($t1, $t2) = explode(' ', microtime());
    return $t2 . ceil($t1 * 1000);
}
发布了119 篇原创文章 · 获赞 12 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/hualaoshuan/article/details/102771639