PHP开发api接口安全验证

浏览:894 发布日期:2018/10/15 分类:技术分享 关键字: api 安全验证 安全
前言

在实际工作中,使用PHP写api接口是经常做的,PHP写好接口后,前台就可以通过链接获取接口提供的数据,而返回的数据一般分为两种情况,xml和json,在这个过程中,服务器并不知道,请求的来源是什么,有可能是别人非法调用我们的接口,获取数据,因此就要使用安全验证。

原理

需要生成签名的参数:

1、did:设备号,即app每个设备的唯一标识

2、version:版本信息,例:v1.0

3、time:时间戳,这里采用的是10位的时间戳

通过以上的字段,通过一定的算法生成sign,然后请求api时带上sign以及以上参数,然后服务器根据接收到的参数使用同样的方法生成sign与接收的sign进行比对,如果一致则通过。

算法

获取当前时间戳,为了保持app与服务器端时间一致,写了个时间获取的函数。

1、使用did,version,time组装成数组

2、键按照字典顺序排序

3、生成did=aaaa&time=123121&version=v1.0

4、进行加密

代码

代码如下:

Aes.php

namespace app\api\controller;
     
    class Aes{
     
        protected $key = 'aaaa13245';
        
        /**
         * AES-128-ECB加密
         * @param  [type] $data [description]
         * @return [type]       [description]
         */
        public function encrypt($data){
     
           $res = openssl_encrypt($data, 'AES-128-ECB', $this->key, OPENSSL_RAW_DATA);
           return base64_encode($res);
        }
        /**
         * AEC-128-ECB解密
         * @param  [type] $data [description]
         * @return [type]       [description]
         */
        public function decrypt($data){
           $res = base64_decode($data);
           $res = openssl_decrypt($res, 'AES-128-ECB', $this->key, OPENSSL_RAW_DATA);
           return $res;        
        }
    }
Auth.php

 namespace app\api\controller;
    use think\Exception;
     
    class Auth{
        
        protected $time = 10;
        /**
         * 验证签名
         * @param  [type] $data [description]
         * @return [type]       [description]
         */
        public static function getSignature($data){
           if(empty($data)){
                 return false;
           }
           ksort($data); //按字典顺序排序
           $query = http_build_query($data);
           //aes加密
           return (new Aes())->encrypt($query);
        }
        /**
         * 解密
         * @param  [type] $str [description]
         * @return [type]      [description]
         */
        public static function checkSignature($str){
            //解密aes
            $data = (new Aes())->decrypt($str['sign']);
            parse_str($data , $sign);
            //验证设备号
            if(empty($sign['did']) || !isset($sign['did']) || $str['did'] != $data['did']){
                throw new Exception('sign验证失败');
            }
            //验证version
            if(empty($sign['version']) || !isset($sign['version'])  || $str['version'] != $data['version']){
                throw new Exception('sign验证失败');
            }
            //验证 时间戳
            if(empty($sign['time']) || !isset($sign['time']) || $str['time'] != $data['time']){
                throw new Exception('sign验证失败');
            }        
            $time = $sign['time'];
            //非调试模式下验证sign过期时间
            if(!config('app_debug')){
                if((time()-$time) > $this->time ){  //已过期
                   throw new Exception('sign已过期');
                }
            }
            return true;
        }
    }
common.php

 namespace app\api\controller;
    use think\Exception;
     
    class Common{
        
        public  $header;
        public function _initialize(){
            //检查sign
            $this->checkSign();
        }
        /**
         * 验证header是否合法
         * @return [type] [description]
         */
        protected function checkSign(){
            
            //sign检查的3点,
            //1:header头中的sign值是否存在,基础验证
            //2:header头中的type是否存在,基础验证
            //3:验证sign是否合法
            $header = request()->header();
     
            if(empty($header['sign']) || !isset($header['sign'])){
                throw new Exception('sign验证失败');
            }
            if(empty($header['type']) || !isset($header['type']) || !in_array($header['type'],$type)){
                throw new Exception('sign验证失败');
            }        
            //验证sign是否合法
            if(Auth::checkSignature($header)){
                $this->header = $header;
            }
        }
        /**
         * 生成测试的sign
         * @return [type] [description]
         */
        public function getSign(){
           //
           //did:设备号
           //version:版本号
           //time:10位时间戳
           $data = [
                'did'      =>  'abdes12545',
                'version'  =>  'v1.0',
                'time'     =>  Time::getTime() 
           ];
           return Auth::getSignature($data);
        }
        public function dSign(){
            $str = 'YZ1mEk23PbRgpUbe6kny978JXcpKDB9qJXsQ0BaeWxG9xEbe/ko16Js8JC4gAMZs';
            return Auth::checkSignature($str);
        }
    }
time.php

namespace app\api\controller;
     
    class Time{
        /**
         * 保证服务器端与app端时间一致
         * @return [type] [description]
         */
        public static function getTime(){
            return time();
        }
    }
欢迎大家来我的博客http://crasphter.cn/article/19交流经验,共同进步
最佳答案
评论( 相关
后面还有条评论,点击查看>>