App架构设计经验谈:服务端接口的设计
App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉。
安全机制的设计
现在,大部分App的接口都采用RESTful架构,RESTFul最重要的一个设计原则就是,客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验证信息。实现上,大部分都采用token的认证方式,一般流程是:
- 用户用密码登录成功后,服务器返回token给客户端;
- 客户端将token保存在本地,发起后续的相关请求时,将token发回给服务器;
- 服务器检查token的有效性,有效则返回数据,若无效,分两种情况:
- token错误,这时需要用户重新登录,获取正确的token
- token过期,这时客户端需要再发起一次认证请求,获取新的token
然而,此种验证方式存在一个安全性问题:当登录接口被劫持时,黑客就获取到了用户密码和token,后续则可以对该用户做任何事情了。用户只有修改密码才能夺回控制权。
如何优化呢?第一种解决方案是采用HTTPS。HTTPS在HTTP的基础上添加了SSL安全协议,自动对数据进行了压缩加密,在一定程序可以防止监听、防止劫持、防止重发,安全性可以提高很多。不过,SSL也不是绝对安全的,也存在被劫持的可能。另外,服务器对HTTPS的配置相对有点复杂,还需要到CA申请证书,而且一般还是收费的。而且,HTTPS效率也比较低。一般,只有安全要求比较高的系统才会采用HTTPS,比如银行。而大部分对安全要求没那么高的App还是采用HTTP的方式。
我们目前的做法是给每个接口都添加签名。给客户端分配一个密钥,每次请求接口时,将密钥和所有参数组合成源串,根据签名算法生成签名值,发送请求时将签名一起发送给服务器验证。类似的实现可参考OAuth1.0的签名算法。这样,黑客不知道密钥,不知道签名算法,就算拦截到登录接口,后续请求也无法成功操作。不过,因为签名算法比较麻烦,而且容易出错,只适合对内的接口。如果你们的接口属于开放的API,则不太适合这种签名认证的方式了,建议还是使用OAuth2.0的认证机制。
我们也给每个端分配一个appKey,比如Android、iOS、微信三端,每个端分别分配一个appKey和一个密钥。没有传appKey的请求将报错,传错了appKey的请求也将报错。这样,安全性方面又加多了一层防御,同时也方便对不同端做一些不同的处理策略。
另外,现在越来越多App取消了密码登录,而采用手机号+短信验证码的登录方式,我在当前的项目中也采用了这种登录方式。这种登录方式有几种好处:
- 不需要注册,不需要修改密码,也不需要因为忘记密码而重置密码的操作了;
- 用户不再需要记住密码了,也不怕密码泄露的问题了;
- 相对于密码登录其安全性明显提高了。
接口数据的设计
接口的数据一般都采用JSON格式进行传输,不过,需要注意的是,JSON的值只有六种数据类型:
- Number:整数或浮点数
- String:字符串
- Boolean:true 或 false
- Array:数组包含着方括号[]中
- Object:对象包含在大括号{}中
- Null:空类型
所以,传输的数据类型不能超过这六种数据类型。以前,我们曾经试过传输Date类型,它会转为类似于"2016年1月7日 09时17分42秒 GMT+08:00"这样的字符串,这在转换时会产生问题,不同的解析库解析方式可能不同,有的可能会转乱,有的可能直接异常了。要避免出错,必须做特殊处理,自己手动去做解析。为了根除这种问题,最好的解决方案是用毫秒数表示日期。
另外,以前的项目中还出现过字符串的"true"和"false",或者字符串的数字,甚至还出现过字符串的"null",导致解析错误,尤其是"null",导致App奔溃,后来查了好久才查出来是该问题导致的。这都是因为服务端对数据没处理好,导致有些数据转为了字符串。所以,在客户端,也不能完全信任服务端传回的数据都是对的,需要对所有异常情况都做相应处理。
服务器返回的数据结构,一般为:
- {
- code:0
- msg: "success"
- data: { key1: value1, key2: value2, ... }
- }
- code: 状态码,0表示成功,非0表示各种不同的错误
- msg: 描述信息,成功时为"success",错误时则是错误信息
- data: 成功时返回的数据,类型为对象或数据
不同错误需要定义不同的状态码,属于客户端的错误和服务端的错误也要区分,比如1XX表示客户端的错误,2XX表示服务端的错误。这里举几个例子:
- 0:成功
- 100:请求错误
- 101:缺少appKey
- 102:缺少签名
- 103:缺少参数
- 200:服务器出错
- 201:服务不可用
- 202:服务器正在重启
错误信息一般有两种用途:一是客户端开发人员调试时看具体是什么错误;二是作为App错误提示直接展示给用户看。主要还是作为App错误提示,直接展示给用户看的。所以,大部分都是简短的提示信息。
data字段只在请求成功时才会有数据返回的。数据类型限定为对象或数组,当请求需要的数据为单个对象时则传回对象,当请求需要的数据是列表时,则为某个对象的数组。这里需要注意的就是,不要将data传入字符串或数字,即使请求需要的数据只有一个,比如token,那返回的data应该为:
- // 正确
- data: { token: 123456 }
- // 错误
- data: 123456
接口版本的设计
接口不可能一成不变,在不停迭代中,总会发生变化。接口的变化一般会有几种:
- 数据的变化,比如增加了旧版本不支持的数据类型
- 参数的变化,比如新增了参数
- 接口的废弃,不再使用该接口了
为了适应这些变化,必须得做接口版本的设计。实现上,一般有两种做法:
- 每个接口有各自的版本,一般为接口添加个version的参数。
- 整个接口系统有统一的版本,一般在URL中添加版本号,比如http://api.domain.com/v2。
大部分情况下会采用第一种方式,当某一个接口有变动时,在这个接口上叠加版本号,并兼容旧版本。App的新版本开发传参时则将传入新版本的version。
如果整个接口系统的根基都发生变动的话,比如微博API,从OAuth1.0升级到OAuth2.0,整个API都进行了升级。
有时候,一个接口的变动还会影响到其他接口,但做的时候不一定能发现。因此,最好还要有一套完善的测试机制保证每次接口变更都能测试到所有相关层面。
写在最后
关于接口设计,暂时想到的就这么多了。各位看官看完觉得有遗漏或有哪些需要优化的欢迎提出一起讨论。
摘自:http://keeganlee.me/post/architecture/20160107
注意:
token 是给用户(登录)用的,appKey/appSecret 是给 应用端(Android、iOS)用的
App架构设计经验谈:服务端接口的设计的更多相关文章
- app微信支付-java服务端接口 支付-查询-退款
个人不怎么看得懂微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录. 首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然也可以自己写完打个jar包) 参数要用jdo ...
- 移动端与PHP服务端接口通信流程设计(增强版)
前面讲过:移动端与PHP服务端接口通信流程设计(基础版) 对于 api_token 的校验,其安全性还可再增强: 增强地方一: 再增加2张表,一个接口表,一个授权表,设计参考如下: 接口表 字段名 字 ...
- 移动端与PHP服务端接口通信流程设计(基础版)
针对 --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效: 2.因为是非开放性的,所以OAuth那套协议是行 ...
- 移动端与PHP服务端接口通信流程设计(基础版)
转载自:http://blog.snsgou.com/post-766.html --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的 ...
- api服务端接口安全
api服务端接口安全性解析 http://blog.csdn.net/tenfyguo/article/details/8225279 常用的基于token的实现方案 http://blog.csdn ...
- App架构设计经验谈:接口”安全机制”的设计
[原文地址 点击打开链接] 原创文章,转载请注明:转载自Keegan小钢 并标明原文链接:http://keeganlee.me/post/architecture/20160107 微信订阅号:ke ...
- 移动端与PHP服务端接口通信流程设计(增强版)
增强地方一: 再增加2张表,一个接口表,一个授权表,设计参考如下: 接口表 字段名 字段类型 注释 api_id int 接口ID api_name varchar(120) 接口名,以"/ ...
- 【规范建议】服务端接口返回字段类型与iOS端的解析
一.本文档的写作目的 App需要跟产品.UI.后台.服务器.测试打交道,app的产出是其他端人员产出的综合体现.与其他端人员沟通就像是开发写接口,也就是面向接口编程的思想. 本文档讲解针对的是服务端返 ...
- 基于CXF框架下的SOAP Webservice服务端接口开发
最近对webservice 进行入门学习,网上也是找了很多的学习资料.总得感觉就是这了解点,那了解点.感觉不够系统,不够容易入门.差不多断断续续看了一个星期了,今天小有成果,把客户端,服务端都搞定了. ...
随机推荐
- C#基础之内存分配
1.创建一个对象 一个对象的创建过程主要分为内存分配和初始化两个环节.在.NET中CLR管理的内存区域主要有三部分:栈.GC堆.LOH堆,栈主要用来分配值类型数据.它的管理是有系统控制的,而不是像GC ...
- Quartz.NET syudy
Quartz.NET Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它 ...
- 分享两个你可能不知道的Java小秘密
引言 最近LZ的工作发生了重大变化,以后博文的更新速度可能会再度回温,希望猿友们可以继续关注. 近期LZ辞掉了项目经理的工作,不过并未离开公司,是转到了基础研发部做更基础的研发,为广大技术人员服务.这 ...
- hello,world!
这可以算是我的第一篇博客了吧?真正意义上的开始... 我于2016年6月毕业于山东英才学院信工学院计算机管理系,至今已有近半年.几经周转,总算是准备稳定下来了.于是,当初的博客想法提上了日程. 本人工 ...
- 最新app store 应用提交经验分享
由于之前提交实在3月份的时候,后来长时间没有提交了,最近又需要提交,发现苹果已经发生翻天覆地的变化了,真是跟不上时代了啊.... 之前提交的基本也是从网上看的,前面的证书安装部分其实基本是一样的没什么 ...
- jquery hasClass、removeClass、addClass方法
hasClass(class) 检查当前的元素是否含有某个特定的类,如果有,则返回true. 参数: class:用于匹配的类名. ---------------------------------- ...
- [C#]Attribute特性
简介 特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联. 特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性. 特性具有以下属性: 特性可向程序中 ...
- .NET Core 在Visual Studio 2015 下的使用-MSDN
.NET Core RC2 现已推出,这是真正的"候选发布"而非 RC1 Beta 冒充的候选发布(如果是那样,请考虑发布后出现的所有更改).当前,围绕 .NET Core 的开发 ...
- shiro 与 web 的结合
本次使用的jar包为 shiro-core-.jar shiro-web-.jar 从Shiro 1.2开始引入了Environment/WebEnvironment的概念,即由它们的实现提供相应的S ...
- Java 集合类详解(含类图)
0.参考文献 此图中蓝色为抽象类.深红色表示接口(Arrays除外).绿色表示具体容器类 1.java集合类图 1.1 1.2 上述类图中,实线边框的是实现类,比如ArrayList,LinkedLi ...