Laravel 接口 简单 签名验证

1、创建中间件VerifyApiSign

secretKey = config('auth.api_sign.secret_key', '');
    }*/
 
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->inExceptArray($request) || ($this->allowTimestamp($request) && $this->signMatch($request))) {
            return $next($request);
        }
        return response()->json([
            'code' =>   '-1',
            'msg' => '签名有误',
            'data' =>   [],
        ]);
    }
 
    /**
     * 判断当前请求是否在忽略列表中
     */
    protected function inExceptArray($request)
    {
        foreach ($this->except as $except) {
            if ($except !== '/') {
                $except = trim($except, '/');
            }
            if ($request->fullUrlIs($except) || $request->is($except)) {
                return true;
            }
        }
        return false;
    }
 
    /**
     * 判断用户请求是否在对应时间范围
     */
    protected function allowTimestamp($request)
    {
        $queryTime = Carbon::createFromTimestamp($request->query('timestamp', 0));
        $lfTime = Carbon::now()->subSeconds($this->timeError);
        $rfTime = Carbon::now()->addSeconds($this->timeError);
        if ($queryTime->between($lfTime, $rfTime, true)) {
            return true;
        }
        return false;
    }
 
    /**
     * 签名验证
     */
    protected function signMatch($request)
    {
        $data = $request->query();
        // 移除sign字段
        if (isset($data['sign'])) {
            unset($data['sign']);
        }
 
        ksort($data);
        $sign = '';
        foreach ($data as $k => $v) {
            if ($this->signField !== $k) {
                $sign .= $k . $v;
            }
        }
 
        if (strtoupper(md5(md5($sign) . $this->secretKey)) === $request->query($this->signField, null)) {
            return true;
        }
        return false;
    }
}

2、打开App\Http\Kernel.php文件,添加我们之前创建的中间件

Laravel 接口 简单 签名验证_第1张图片

3、控制器模拟测试方法

public function test(){
        //timestamp和sign为固定传入值,sign使用加密方法加密。
        $time = time();
        $array = [
            'list' => 1,
            'timestamp' => $time,
            'sign' => ''
        ];
        $sign = $this->arithmetic($array);
        $array['sign'] = $sign;
        /*$paramStr = '';
        foreach ($array as $k => $v) {
            $paramStr = $paramStr . $k . '=' . $v . '&';
        }*/
        $url_str = http_build_query($array);
        $url = "http://test.com/api/test?".$url_str;
        $result = $this -> httpGet($url);
        print_r($result );exit;
    }
 
 
    /**
     * 签名加密
     * 1. 对加密数组进行字典排序 防止因为参数顺序不一致而导致下面拼接加密不同
     * 2. 将Key和Value拼接
     * 3. 通过双层md5,第一次md5参数,第二次加密第一次md5后的数据拼接私密串进行二次加密,加密后并转化为大写获得签名sign
     * @param [type] $arr
     * @return void
     */
    private function arithmetic($arr){
 
        ksort($arr);
        $sign = '';
        foreach ($arr as $k => $v) {
            if ('sign' !== $k) {
                $sign .= $k . $v;
            }
        }
        $secretKey = '';
        $sign = strtoupper(md5(md5($sign) . $secretKey))
        return $sign;
    }
 
    /**
     * get请求
     *
     * @param [type] $url
     * @return void
     */
    private function httpGet($url){
        $curl = curl_init();
        curl_setopt($curl,CURLOPT_URL,$url);
        curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

你可能感兴趣的:(laravel,PHP,php,laravel,签名)