PHP API 接口访问之签名验证

设计思路:1、前后端商定统一的加密规则;2、后端配置文件保存固定的验证字符串;3、对前端传的加密sign进行合法性验证、时效验证、唯一性验证;

代码如下:

1、验证前端传过来的sign(抛出异常的接口是我自己框架封装的接口,没封装可以改成Exception)

  

<?php
/**
 * Created by PhpStorm.
 * User: hjx(2896751917@qq.com)
 * Date: 2019/2/21
 */

namespace app\api\controller;


use app\common\lib\exception\ApiException;
use app\common\lib\extend\Aes;
use think\Cache;
use think\Controller;
use think\Request;

class Common extends Controller
{
    protected $apiToken = null;

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
        $this->verifyToken();
    }

    /**
     * 访问API时进行sign验证
     * @return bool
     * @throws ApiException
     */
    public function verifyToken() {
        $data = input('param.');

        $validate = validate('Common');
        if(!$validate->check($data)) {
            throw new ApiException($validate->getError(), 400);
        }

        $str = (new Aes())->decrypt($data['sign']);
        if(!$str) {
            throw new ApiException('sign不合法', 401);
        }

        list($t1,$t2) = explode('&',$str);
        //sign失效时间
        if(time() - $t1 > 600) {
            throw new ApiException('sign已过期', 401);
        }
        //验证规则
        if($t2 != config('api.CorpId')) {
            throw new ApiException('sign不合法', 401);
        }
        //验证sign唯一性
        if(Cache::get($data['sign'])) {
            throw new ApiException('sign已使用过', 401);
        }

        Cache::set($data['sign'],1,3600);

        return true;
    }

}

  

  

  2、各个控制器都继承上面的Common控制器即可


3、后台加密规则
<?php
/**
 * Created by PhpStorm.
 * User: hjx
 * Date: 2019/3/12
 * Time: 10:41
 */

namespace app\api\controller;

use app\common\lib\extend\Aes;

class Test
{
    /**
     * token创建规则,以后前端得按照这个规则进行
     * @return \app\common\lib\extend\HexString
     */
    public function createToken() {
        $str = time().'&'.config('api.CorpId');
        return (new Aes())->encrypt($str);
    }
}

  后台加密只是示例的加密规则,可以给前端按照这种加密方式进行加密得到sign