接口书写注意事项

接口书写注意事项

1.文档要写周全,需要的每个字段,规定是什么类型,什么含义要标柱清楚,写完接口后自己先测试一下是否通过,不要直接扔给测试或者开发,然后反应错误了在进行修改

2. 接口要做到小,同时比较多,切记一个接口的代码量很多。做到接口要小而多,不要做大而全,以方便减少服务器的压力


3. 在做app接口的返回值的数据类型时需要注意,弱语言和强语言的处理数据类型毕竟不同,比如空数组的返回至少要初始化一个,这样可以让一些客户端处理起来方便,而不会因为一些数据的不正常造成 crash,还有就是错误返回的标准统一周全,以及返回适当的错误提示


4. 当数据库里的字段发生变更时,要及时更新文档,并和使用到的程序员和测试人员说一声


5.接口的测试(如果是Node.Js / MongoDB 的搭配,也可以弄个自动化测试),测试要包含所有的返回情况,接口的规范,可以遵循 RESTfull API


6.还有个需要注意的,可能是 content-type ,返回的是 json 数据,最好就是 application/json ,客户端一般都会用第三方的网络请求组件,而一些组件对 content-type 有严格的限制,当然这个需要和客户端的程序员确认,避免你明明返回 json 在 text 下可以正常显示,客户端却无法解析出来


7.我们的接口一般是给app用的, 接口要加密。每次回话前 都向服务器请求token,服务器以session存储,回话结束,就销毁

8. 用restful,最好开启https,不然会被坑死的,运营商,浏览器,路由器一般发现4XX,5XX状态,喜欢替换成自己的广告,如果不用restful,返回的都是200状态,就不会被替换成运营商或路由器自己的导航页了,运营商,路由器容易擅自根据403,404状态推自己的导航页


常见的问题

如果服务端采取了防重放机制,要求http请求带上时间戳,和服务器的时间误差超过一段距离则请求不合法。那么,客户端的时间戳不一定是正确的(有可能用户改了系统时间),这种方案该怎么调整?


(1)第一次启动从服务器获取一次时间,之后客户端自动计数维护这个时间,每秒加一,这样就跟服务器时间一致了 
(2):应该是需要时间戳的请求。带上服务器的时间戳。比如说修改个人资料。是请求个人资料。客户端修改。发送修改后的个人资料。在请求个人资料的时候服务器就带上时间戳。最好是上面所说的token。我们可以验证这个时间戳。发送的时候带上这个时间戳或者token

关于session:

APP登录没有了网页的session,怎么处理的?

1、jwt oauth - slee
2、app一般通过token来进行登录验证 
3、就是登录返回APP一个token,保存在客户端,下次传递这个token来验证身份

一次请求算一个会话?还是token是有时效的?

1token是有时效的,可以去更新-蜗牛
2token 不保存到客户端本地。 - windk

每次请求前必须过去一次?

1、对,时效时间内,多次请求 可以只取一次 - windk
2token这个属于安全性的东西 取决于信息的重要性 通常来说安全性要求越高,所要做的活就越,我们大致换了经历过三种方面:
第一种 直接在 header里传用户名 密码 最简单,但最不安全。
第二种 就在客户端种cookie 这个跟web一样了。
第三种 就是用token 用一定的规则生成token 客户端每次请求带token 服务端用同一规则生成tokentoken有效时间 放到token加密规则里 省得再验证一个时间戳

app用户登录的模型

理论版的描述如下:

(1) 服务器接收到app发送的用户名和密码后,验证用户名和密码是否正确。
  如果错误则返回错误信息。
  如果验证正确,生成一个随机的不重复的token字符串(例如"daf32da456hfdh"),在redis或memcache中维护一个映视表,建立token字符串和用户信息的对应关系表,
  例如,把token字符串"daf32da456hfdh"和用户id"5"对应起来。
(2) 服务器把token字符串返回给app,app把这个token字符串保存起来,作为登录的验证。
(3) 当需要验证用户身份的操作时,必须要把token字符串传给服务器验证身份。
例如,api "test.com/user/update"是更新用户的信息,必须要验证用户的身份.
当调用api "test.com/user/update"时,把token字符串"daf32da456hfdh"
放在url上,变成"test.com/user/update?token=daf32da456hfdh" .

  当服务器接收到这个api请求,知道要验证用户身份的,于是,就把参数中token的值"daf32da456hfdh"取出来,在(1)中建立的token字符串和用户信息的对应关系表查找,如果发现没这个token值的,则返回验证失败的信息。如果发现有这个token值,则获取这个用户的信息,进行相关的更新操作。
  (4) 当用户退出登录时,需要通过调用api,让服务器把这个用户对于的token字符串删除.
  例如,api "test.com/user/logout"是退出登录的api,也要验证用户身份, 则调用"test.com/user/logout?token=daf32da456hfdh" 。当服务器接到退出登录的api请求时,在(1)中建立的token字符串和用户信息的对应关系表查找token字符串,把token和用户信息都删除即可。

注意:这个方案并不是十分安全,这个身份验证是依赖于token字符串。如果用户泄漏了自己的url, 那很大程度上token也被别人泄漏了,就相当于钥匙被人复制了一份。在下篇的通讯安全中,会描述一个防止token在通讯中泄漏的方案。
restful风格接口设计方案:
http://blog.sina.com.cn/s/blog_6c3ac4480102w8qx.html



/**
 * 数据操作类
 */
class Request
{
    //允许的请求方式
    private static $method_type = array('get', 'post', 'put', 'patch', 'delete');
    //测试数据
    private static $test_class = array(
        1 => array('name' => '托福班', 'count' => 18),
        2 => array('name' => '雅思班', 'count' => 20),
    );

    public static function getRequest()
    {
        //请求方式
        $method = strtolower($_SERVER['REQUEST_METHOD']);
        if (in_array($method, self::$method_type)) {
            //调用请求方式对应的方法
            $data_name = $method . 'Data';
            return self::$data_name($_REQUEST);
        }
        return false;
    }

    //GET 获取信息
    private static function getData($request_data)
    {
        $class_id = (int)$request_data['class'];
        //GET /class/ID:获取某个指定班的信息
        if ($class_id > 0) {
            return self::$test_class[$class_id];
        } else {//GET /class:列出所有班级
            return self::$test_class;
        }
    }

    //POST /class:新建一个班
    private static function postData($request_data)
    {
        if (!empty($request_data['name'])) {
            $data['name'] = $request_data['name'];
            $data['count'] = (int)$request_data['count'];
            self::$test_class[] = $data;
            return self::$test_class;//返回新生成的资源对象
        } else {
            return false;
        }
    }

    //PUT /class/ID:更新某个指定班的信息(全部信息)
    private static function putData($request_data)
    {
        $class_id = (int)$request_data['class'];
        if ($class_id == 0) {
            return false;
        }
        $data = array();
        if (!empty($request_data['name']) && isset($request_data['count'])) {
            $data['name'] = $request_data['name'];
            $data['count'] = (int)$request_data['count'];
            self::$test_class[$class_id] = $data;
            return self::$test_class;
        } else {
            return false;
        }
    }

    //PATCH /class/ID:更新某个指定班的信息(部分信息)
    private static function patchData($request_data)
    {
        $class_id = (int)$request_data['class'];
        if ($class_id == 0) {
            return false;
        }
        if (!empty($request_data['name'])) {
            self::$test_class[$class_id]['name'] = $request_data['name'];
        }
        if (isset($request_data['count'])) {
            self::$test_class[$class_id]['count'] = (int)$request_data['count'];
        }
        return self::$test_class;
    }

    //DELETE /class/ID:删除某个班
    private static function deleteData($request_data)
    {
        $class_id = (int)$request_data['class'];
        if ($class_id == 0) {
            return false;
        }
        unset(self::$test_class[$class_id]);
        return self::$test_class;
    }
}

3、接口的分类:

1)本公司自己的接口
大体思路:小白用户根据说明文档,调用封装好的接口,也就是访问自己的控制器,直接判断返回json格式即可
2)别人请求自己接口,自己去别的接口调用数据返回小白用户
大体思路:通过异步请求,将数据取回转义成自己公司的接口格式,返回给小白用户。

简单的介绍了一下接口的一些注意事项,若有不正确的欢迎留言指正,谢谢

你可能感兴趣的:(PHP)