zoukankan      html  css  js  c++  java
  • 一个严谨的接口调用

    入口

    use ApisFactory;
    use fingerLog;
    
    class IndexController extends CommoncontrollersApi
    {
        /**
         * API入口。
         * 普通 POST 方式提交。
         */
        public function indexAction()
        {
            // [1]
            define('IS_API', true);
            header("Access-Control-Allow-Origin: *");
            header('Content-type: application/json');
            // [2]
            $params = [
                'post'  => $this->_request->getPost(),
                'input' => file_get_contents('php://input')
            ];
            // [3]
            $apiObj = Factory::factory($params);
            $result = $apiObj->getResult();
    
            // [4] 记录响应日志。
            Log::writeApiResponseLog($result);
            // [5] 输出结果。
            echo json_encode($result, JSON_UNESCAPED_UNICODE);
            // [6]
            $this->end();
        }
    }
    

    工厂验证

     /**
         * 根据接口名称返回接口对象。
         * 
         * -- 1、接口名称转类名称规则:user.login = UserLoginApi
         * -- 2、当 method 参数为空的时候,要抛出异常给调用的人捕获处理。
         *
         * @param  array  $apiData 请求来的所有参数。
         * @throws Exception
         * @return Api
         */
        public static function factory(&$apiData)
        {
            // [1]
            $reqParams = DecodeAdapter::parse($apiData);
            self::writeRequestLog($apiData, $reqParams);
            // [2]
            if (!isset($reqParams['method']) || strlen($reqParams['method']) === 0) {
                Core::exception(STATUS_METHOD_NOT_EXISTS, 'method does not exist');
            }
            if (!isset($reqParams['v']) || strlen($reqParams['v']) === 0) {
                Core::exception(STATUS_VERSION_NOT_EXISTS, 'version number is wrong');
            }
            if (!isset($reqParams['appid']) || strlen($reqParams['appid']) === 0) {
                Core::exception(STATUS_APPID_NOT_EXISTS, 'appid parameters cannot be empty');
            }
            if (!isset($reqParams['timestamp']) || strlen($reqParams['timestamp']) === 0) {
                Core::exception(STATUS_TIMESTAMP_NOT_EXISTS, 'timestamp parameters cannot be empty');
            }
    
            // [3] 将 method 参数转换为实际的接口类名称。
            $apiName   = $reqParams['method'];
            $params    = explode('.', $apiName);
            $classname = '';
            foreach ($params as $param) {
                $classname .= ucfirst($param);
            }
            // 1.0.0 => v1_0_0
            $version = str_replace('.', '', $reqParams['v']);
    
            // [4]
            $apiDir = self::apiDir($reqParams['method']);
            if (strlen($apiDir) > 0) {
                $apiDir = "{$apiDir}\";
            }
    
            // [5] 读取 appid 配置信息。
            $apiDetail = self::getApiDetail($reqParams['appid']);
    
            // [6] IP 限制判断。
            $ip   = Ip::ip();
            $bool = ApiAuth::checkIpAllowAccess($apiDetail, $ip);
            if ($bool == false) {
                Core::exception(STATUS_IP_FORBID, '受限 IP 不允许访问');
            }
    
            // [7] 映射接口类。
            $classname = "\Apis\{$apiDetail['api_type']}\v{$version}\{$apiDir}{$classname}Api";
            if (strlen($apiName) && class_exists($classname)) {
                return new $classname($reqParams, $apiDetail['api_type'], $apiDetail['api_key'], $apiDetail['api_secret']);
            } else {
                Core::exception(STATUS_API_NOT_EXISTS, '您的 APP 太旧请升级!');
            }
        }
    

    类验证

    /**
         * 构造方法。
         *
         * @param  array   $data       所有请求过来的参数。
         * @param  string  $apiType    API 接口类型。
         * @param  string  $apiKey     接口标识。
         * @param  string  $apiSecret  接口密钥。  
         *
         * -- 1、合并提交的参数。
         * -- 2、调用权限判断。
         * -- 3、签名验证。
         * -- 4、参数格式判断。
         * -- 5、运行接口逻辑。
         */
        public function __construct(&$data, $apiType, $apiKey = '', $apiSecret = '')
        {
            $this->apiType   = $apiType;
            $this->timestamp = $_SERVER['REQUEST_TIME'];
            $this->params    = $data;
            $this->apiKey    = $apiKey;
            $this->apiSecret = $apiSecret;
    
            $this->checkIpAccessPermission();
    
            $this->checkTimeLag();
    
            $this->checksignature();
    
            $this->runService();
        }
    
    

    签名验证

    /**
         * 验证码请求签名。
         * 
         * @param  array  $params     请求参数。
         * @param  string $apiSecret  API 密钥。
         *
         * @return bool
         */
        public static function checkSign($params, $apiSecret)
        {
            $sign = $params['sign'];
            unset($params['sign']);
            ksort($params);
            $str = '';
            foreach ($params as $key => $value) {
                if (!is_array($value) && strlen($value) != 0) {
                    $str .= "{$key}{$value}"; // 非数组的值才能进行签名。
                }
            }
            $str    = $str . $apiSecret;
            $okSign = strtoupper(md5($str));
            if (App::getConfig('app.env') != ENV_DEV) {
                if (strlen($sign) === 0 || $sign != $okSign) {
                    Core::exception(STATUS_SERVER_ERROR, 'API signature error');
                }
            }
        }
    

    各种验证,太可怕了。

  • 相关阅读:
    (转)android res文件夹里面的drawable(ldpi、mdpi、hdpi、xhdpi、xxhdpi)
    ListView模拟微信好友功能
    最小生成树(普利姆算法、克鲁斯卡尔算法)
    Android Afinal框架学习(二) FinalActivity 一个IOC框架
    浅谈WebLogic和Tomcat
    变量定义和声明的差别(整理)
    浏览器内核分类
    设计模式 之 享元
    FPGA中浮点运算实现方法——定标
    兔子--Android中的五大布局
  • 原文地址:https://www.cnblogs.com/jiqing9006/p/12109428.html
Copyright © 2011-2022 走看看