api数据安全之sign校验



1:前端:根据key,将当前13位时间戳通过aes加密生成的密文放到header请求头的sign属性中
2:后端:接收header头的sign属性的值,通过aes解密,得到13位时间戳。如果时间戳的时间是五秒之前的或者大于当前时间。
    则sign错误不予放行;
 
 
php代码
 
common.php
<?php
namespace app\api\controller;
use think\Controller;
use app\common\lib\IAuth;
use think\Facade\Cache;
// API模块 公共的控制器
class Common extends Controller
{
    public $headers = '';
    // 初始化的方法
    public function __construct(){
        // 校验sign值
        $this->checkRequestAuth();
        parent::__construct();
    }
    // 检查每次app请求的数据是否合法
    public function checkRequestAuth(){
        // 实现需要获取headers的数据
        $headers = request()->header();
        
        // 基础参数校验
        if(empty($headers['sign'])){
            AException('sign不存在', 401);
        }
        if(!IAuth::checkSignPass($headers['sign'])){
            AException('sign校验失败', 401);
        }

        // 通过,存入缓存(实现sign的使用即失效
        Cache::set($headers['sign'], 1, config('IAuth.sign_cache_time'));
        // 存到成员属性中,供子类调用
        $this->headers = $headers;
    }
    
}

IAuth.php

<?php
/** .-------------------------------------------------------------------
 * | Author: OkCoder <1046512080@qq.com>
 * | Git: https://www.gitee.com/okcoder
 * | Copyright (c) 2012-2019, www.i5920.com. All Rights Reserved.
 * '-------------------------------------------------------------------*/

namespace app\common\lib;
use think\Facade\Cache;
class IAuth
{
    /**
     * 设置密码
     * @param string $data 字符串
     * @return string
     */
    public static function setPassword($str)
    {
       return md5($str.config('IAuth.password_salt'));
    }

    /**
     * 模拟前端工程师加密。生成每次请求的sign
     * @param string $data 字符串
     * @return string
     */
    public static function setSign($time = '')
    {
        if(empty($time)) $time = Time::get13TimeStamp();
        // 加密
        $res = Aes::encode($time);
        return $res;
    }
    /*
    * 检测每次生成的sign
    */
    public static function checkSignPass($sign){
        // 解密
        $str = Aes::decode($sign);

        // 数据规则
        if(!$str || !is_numeric($str)){
            return false;
        }
        // 测试时间戳,如果时间戳是五秒前的则错误
        $now = Time::get13TimeStamp();
        if( $now - $str > config('IAuth.sign_time') ||  $str > $now){
            return false;
        }
        // 如果缓存中有该sign,即sign使用过,不放行
        if(Cache::get($sign)){
            return false;
        }
        return true;
    }

}

Aes.php

<?php
/** .-------------------------------------------------------------------
 * | Author: OkCoder <1046512080@qq.com>
 * | Git: https://www.gitee.com/okcoder
 * | Copyright (c) 2012-2019, www.i5920.com. All Rights Reserved.
 * '-------------------------------------------------------------------*/

namespace app\common\lib;
class Aes
{
    /**
     * 解密字符串
     * @param string $data 字符串
     * @return string
     */
    public static function decode($str)
    {
        // AES模式不用vi偏移值
        return openssl_decrypt(base64_decode($str),"AES-128-ECB",config('Aes.key'),OPENSSL_RAW_DATA);
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    public static function encode($str)
    {
        //密钥 须是16位
        return base64_encode(openssl_encrypt($str,"AES-128-ECB",config('Aes.key'),OPENSSL_RAW_DATA));
    }

}

 

posted @ 2020-03-15 17:50  cl94  阅读(1115)  评论(0编辑  收藏  举报