一、app视图与控制器

1)路由

这里的v1、v2就是模块,由于客户端版本一直在迭代的,那么一些老版本的客户端调用的接口就得保留起来,使得兼容。新版本就直接调用新接口。

还有一种是写html页面,在客户端展示,只要把template文件夹和data文件夹加上就可以了。

Controller的配置如下,注意ismodule是true,module_list中的array:

$InitPHP_conf['ismodule'] = true; //开启module方式
$InitPHP_conf['controller']['path']                  = 'controller';
$InitPHP_conf['controller']['controller_postfix']    = 'Controller'; //控制器文件后缀名
$InitPHP_conf['controller']['action_postfix']        = ''; //Action函数名称后缀
$InitPHP_conf['controller']['default_controller']    = 'index'; //默认执行的控制器名称
$InitPHP_conf['controller']['default_action']        = 'index'; //默认执行的Action函数
$InitPHP_conf['controller']['module_list']           = array('v1','v2'); //module白名单
$InitPHP_conf['controller']['default_module']        = 'v1'; //默认执行module
$InitPHP_conf['controller']['default_before_action'] = 'before'; //默认前置的ACTION名称
$InitPHP_conf['controller']['default_after_action']  = 'after'; //默认后置ACTION名称

这里顺便说下InitPHP的路由管理。InitPHP的框架URL路由分为三种形式,原生、path模式、rewrite模式,HTML模式。我这边用的是rewrite模式。

1.原生模式:index.php?c=index&a=run

2.rewrite模式:/index/run/id=1 (需要开启服务器rewrite模块,并且配置.htaccess)

3.path模式:/index/run/id/1 (需要开启服务器rewrite模块,并且配置.htaccess)

4.html模式: user-index-run.htm?uid=100 (需要开启服务器rewrite模块,并且配置.htaccess)

2)模拟session

这里模拟的方法比较简单而粗暴。

在登录的时候,会生成一串字符,然后保存到用户表中,这串字符会返回给客户端,作为session。

在登录后客户端会将这串字符传过来,服务器再根据这串字符在搜索用户,从未获取用户信息,并判断是否已经登录。

二、apiController通用控制器类

public function __construct() {
        parent::__construct();

        $this->controller_name = $this->getC();
        $this->action_name = $this->getA();
        $this->module_name = $this->getM();

        //访问参数日志记录
        $this->_logVisit();

        //API统一接口为post提交
        if (!$this->controller->is_post()) {
            $this->output(constHelper::API_STATUS_NEED_POST, '必须为POST请求');
        }

        /**
         * 请求参数示例
         * __ua=Android 4.4.4//MI 3W//26//2.0//865645022129866//////WIFI&
         * __timestamp=1441854121116&
         * mobile=13800138000&
         * __version=2.0&
         * __device=android&type=2&
         * __key=67543fd413ce4d281fc93306597acb66
         */
        $device = $this->p('__device'); //客户端名称
        $timestamp = $this->p('__timestamp'); //客户端时间戳
        $key = $this->p('__key'); //客户端加密指纹
        $session = $this->p('__session'); //客户端SESSION
        $version = substr($this->p('__version'), 0, 5); //客户端版本

        //客户端最低版本号要求
        if (strnatcmp($version, constHelper::MIN_VERSION_ALLOWED) < 0) { //客户端需要升级
            $this->output(constHelper::API_STATUS_NEED_UPGRADE, '客户端需要升级');
        }

        //检查密钥
        $this->_checkSecretKey($device, $timestamp, $key);

        //判断是否需要验证登录
        $needCheck = $this->_checkLogin();
        if($needCheck && empty($session)) {
            $this->output(constHelper::API_STATUS_NEED_LOGIN, '请先登录');
        }

        //根据session获取用户信息
        if(!empty($session)){
            $memberModel = InitPHP::getMysqlDao('member');
            $this->member = $memberModel->getMemberBySession($session);
        }

        //session没有获取到相关信息 也要做跳转
        if($needCheck && empty($this->member)) {
            $this->output(constHelper::API_STATUS_NEED_LOGIN, '请先登录');
        }
}

1)访问参数日志记录

当客户端发起一个请求的时候,会带上很多参数,例如操作系统、当前版本号、时间戳、口令、网络、应用市场等信息。

调用$this->_logVisit();将这些信息全部存到MongoDB中,便于以后调试与追踪。并且在返回参数的时候,将返回参数更新到这条请求记录中。

2)output返回参数

返回参数的格式如下:

 {
    "code":1000,
    "msg":"hello\u6210\u529f",
    "data":{
        "result":1,
        "obj":{"id":"55f57a4aa0105"}
    }
}    

code:是各种通用的错误编码,我写在了libraray/helper/dict/constHelper中,如上面的代码所示,当验证出现错误的时候,会显示响应的code,并返回

msg:就是提示语言,这里做了Unicode编码

data:返回的就是各种自定义参数,这里仅列举了通用的两种

result:也是类似于code的定义,不同的是针对的是特定请求中的返回码

obj:返回的就是个自定义对象,也可以是数组

3)密钥匹配

为了保证请求的合法性,在客户端和服务器端约定一个密钥,客户端在根据这个密钥做加密后,传过来给服务器端,服务端再加密然后做匹配。

服务器端将密钥设置在defined文件中,IOS,Android可以定义的不同:

define('API_IOS_KEY', 'DF_A98=D^&7$^%*9CNAhj0UO!!LM11');
define('API_ANDROID_KEY', 'KU98&)dsf8%@kji89dfadJK-800i122');
define('API_UNKNOW_KEY', 'jfdsfd798hj+@(*kb66578-223q670933');

而验证的规则也很简单,时间戳+密钥再MD5加密:

private function _checkSecretKey($device, $timestamp, $key) {
        //提取私有密钥
        $privateKey = '';
        switch (strtolower($device)) {
            case 'ios':
                $privateKey = API_IOS_KEY;
                break;
            case 'android':
                $privateKey = API_ANDROID_KEY;
                break;
            default:
                $privateKey = API_UNKNOW_KEY;
                break;
        }

        $keySource = $privateKey . $timestamp;
        //客户端安全认证失效
        if (empty($key) || ($key != md5($keySource))) {
            $this->outputCom(constHelper::API_STATUS_AUTH_FAIL, '安全认证失败');
        }
}

4)各种验证

1.第一个验证是只接收post请求,这里直接使用了InitPHP中的Request API

2.客户端最低版本号验证,有时候客户端需要强制升级

3.登录验证,这里有多种情况,有些API是不需要登录的,有些是需要登录的,而有些是既可以登录也可以不登录

三、API调试工具

在交付给客户端之前,自己肯定要先测试一下的,这就需要一个简易工具了,当然也可以选择一些强大的工具,例如firefox的httprequester等。

在tool文件夹下面,我已经把这个工具放在里面了,执行页面如下:

工具的文件目录也很淳朴,就五个文件,有两个地方需要配置:

1)在indexhtml中data-domain属性,修改为你当前的api域名,在第13行左右

2)在tk.php中,修改数据库连接参数,以及客户端密钥

GitHub地址:

https://github.com/pwstrick/grape

grape动态PHP结构(三)——API接口的更多相关文章

  1. grape动态PHP结构(一)——目录结构与配置文件

    一.结构介绍 结构的名字grape,中文名叫葡萄,因为最近一个同事经常带葡萄到公司给我们吃,受到启发想到了这个名字. 1)本结构需要在PHP5.5中运行,如果要在5.4中运行,有些地方就要做些修改 2 ...

  2. grape动态PHP结构(二)——管理后台

    一.概述

  3. ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段

    ASP.NET实现二维码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;us ...

  4. coreseek实战(三):全文搜索在php中应用(使用api接口)

    coreseek实战(三):全文搜索在php中应用(使用api接口) 这一篇文章开始学习在php页面中通过api接口,使用coreseek全文搜索. 第一步:综合一下前两篇文章,coreseek实战( ...

  5. 操作系统的三个接口 shell gui api

    操作系统的三个接口 shell gui api 编程语言是用来告诉操作系统干什么的语言. 编程语言是人机交互语言. 程序.进程:任务集.

  6. itnesse实现api接口自动化测试学习

    上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接口测试的时候,就是只在浏览器里人工测试 ...

  7. 利用fitnesse实现api接口自动化测试

    上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,仔细想想,我做接口测试也有几个年头了,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接 ...

  8. Qt插件开发入门(两种方法:High-Level API接口,Low-Level API接口)

    Qt中为我们提供了两种开发插件的方式.一种是使用High-Level API接口,一种是使用Low-Level API接口.所谓High-Level API 是指通过继承Qt为我们提供的特定的插件基类 ...

  9. 干货来袭-整套完整安全的API接口解决方案

    在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...

随机推荐

  1. myeclipse9中导入的jquery文件报错(出现红叉叉,提示语法错误)

    选中报错的js文件, 右键选择 MyEclipse-->Exclude From Validation : 然后继续右键执行MyEclipse-->Run Validation 即可

  2. 嵌入式Linux驱动学习之路(二)u-boot体验

    u-boot工程简介 现在的u-boot支持PowerPC.ARM.X86.MIPS体系结构的上百种开发板,已经称为功能最多.灵活性最强,并且开发最积极的开源Bootloader.目前由DENX的Wo ...

  3. BZOJ4610——[Wf2016]Ceiling Functi

    水题一道,不是很懂为啥没人做... 1.题意:纠正一下..bzoj的题意不是很对...注意不是堆,是不平衡的二叉树,就是非旋转的treap, 另外...插入的时候,小于插在左边..大于等于插在右边 2 ...

  4. 客户端HTTP断点续传的原理

    其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已. 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:假设服务器域名为wwww.scu.edu.cn,文件名为down. ...

  5. php远程抓取网站图片并保存

    以前看到网上别人说写程序抓取网页图片的,感觉挺神奇,心想什么时候我自己也写一个抓取图片的方法! 刚好这两天没什么事,就参考了网上一个php抓取图片代码,重点借鉴了 匹配img标签和其src属性正则的写 ...

  6. SQL的常用语句

    select * from g_members where id between '16' and '31' order by id desc 倒序排列 select * from g_members ...

  7. 2016 - 1 - 21 RunloopMode中的Source 与Observer

    一:CFRunLoopSourceRef 1.CFRunLoopSourceRef是事件源(输入源) 2.按照官网文档分为,Source可以分为以下几类: 2.1 Porl - Based Sourc ...

  8. URL重写以后发布到IIS找不到页面

    1.读取必须勾选,否则无法加载资源文件(img,css等) c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll

  9. 试读《基于MVC的JavaScript Web富应用开发》

    前两年做jsp开发时,用了不少JavaScript(JS)和Ajax, 最近的项目一直在使用Flex做前台,虽然也有类似的ActionScript实现JS的功能,但没想到的是,短短几年JS发展如此迅速 ...

  10. 面向切面编程(AOP)及其作用

    在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用. 1.面向切面编程(AOP) 面向切面编程(AOP)就是对软件系统不同关注点的分离,开发者通过拦截方法调用并在方法调用前后添加辅助代码. ...