App 接口的设计

本贴最后更新于 2503 天前,其中的信息可能已经时异事殊

App 与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉。

一、安全机制的设计

现在,大部分 App 的接口都采用 RESTful 架构,RESTFul 最重要的一个设计原则就是,客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验证信息。实现上,大部分都采用 token 的认证方式,一般流程是:

  1. 用户用密码登录成功后,服务器返回 token 给客户端;
  2. 客户端将 token 保存在本地,发起后续的相关请求时,将 token 发回给服务器;
  3. 服务器检查 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 取消了密码登录,而采用手机号 + 短信验证码的登录方式,我在当前的项目中也采用了这种登录方式。这种登录方式有几种好处:

  1. 不需要注册,不需要修改密码,也不需要因为忘记密码而重置密码的操作了;
  2. 用户不再需要记住密码了,也不怕密码泄露的问题了;
  3. 相对于密码登录其安全性明显提高了。

二、接口数据的设计

接口的数据一般都采用 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
message: "success"
data: { key1: value1, key2: value2, ... }
}

  • code: 状态码,0 表示成功,非 0 表示各种不同的错误
  • message: 描述信息,成功时为”success”,错误时则是错误信息
  • data: 成功时返回的数据,类型为对象或数据

不同错误需要定义不同的状态码,属于客户端的错误和服务端的错误也要区分,比如 1XX 表示客户端的错误,2XX 表示服务端的错误。这里举几个例子:

  • 0:成功
  • 100:请求错误
  • 101:缺少 appKey
  • 102:缺少签名
  • 103:缺少参数
  • 200:服务器出错
  • 201:服务不可用
  • 202:服务器正在重启

错误信息一般有两种用途:一是客户端开发人员调试时看具体是什么错误;二是作为 App 错误提示直接展示给用户看。主要还是作为 App 错误提示,直接展示给用户看的。所以,大部分都是简短的提示信息。

data 字段只在请求成功时才会有数据返回的。数据类型限定为对象或数组,当请求需要的数据为单个对象时则传回对象,当请求需要的数据是列表时,则为某个对象的数组。这里需要注意的就是,不要将 data 传入字符串或数字,即使请求需要的数据只有一个,比如 token,那返回的 data 应该为:

// 正确
data: { token: 123456 }

// 错误
data: 123456

三、接口版本的设计

接口不可能一成不变,在不停迭代中,总会发生变化。接口的变化一般会有几种:

  • 数据的变化,比如增加了旧版本不支持的数据类型
  • 参数的变化,比如新增了参数
  • 接口的废弃,不再使用该接口了

为了适应这些变化,必须得做接口版本的设计。实现上,一般有两种做法:

  1. 每个接口有各自的版本,一般为接口添加个 version 的参数。
  2. 整个接口系统有统一的版本,一般在 URL 中添加版本号,比如 http://api.domain.com/v2

大部分情况下会采用第一种方式,当某一个接口有变动时,在这个接口上叠加版本号,并兼容旧版本。App 的新版本开发传参时则将传入新版本的 version。

如果整个接口系统的根基都发生变动的话,比如微博 API,从 OAuth1.0 升级到 OAuth2.0,整个 API 都进行了升级。

有时候,一个接口的变动还会影响到其他接口,但做的时候不一定能发现。因此,最好还要有一套完善的测试机制保证每次接口变更都能测试到所有相关层面。

整理来源:Keegan 小钢

  • 加密
    16 引用 • 41 回帖
  • 设计
    112 引用 • 797 回帖 • 1 关注
  • token

    令牌、凭证、代币、记号,whatever...

    7 引用 • 14 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • encoredw 1

    💛 💙 💜 ❤️ 💚

  • 其他回帖
  • lijp 1

    mark 很不错。

  • kinosang

    HTTPS 的成本并不高,尤其是现在已经有 Let's Encrypt 的免费 DV SSL 的情况下。

    自己造的 token 认证机制只有自己在审计,然而成熟的公开标准的机制有无数眼睛盯着看,安全性上还是后者有保障

  • someone 1

    大神

  • 查看全部回帖

推荐标签 标签

  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 181 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 628 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 410 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 742 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 126 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 179 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    21 引用 • 58 回帖
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    133 引用 • 3655 回帖
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 3 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 602 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    77 引用 • 1738 回帖 • 1 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖 • 1 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 2 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    492 引用 • 1384 回帖 • 365 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 695 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    20 引用 • 74 回帖 • 3 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 111 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 1 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 12 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1347 回帖 • 1 关注
  • 笔记

    好记性不如烂笔头。

    305 引用 • 780 回帖
  • 音乐

    你听到信仰的声音了么?

    59 引用 • 509 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖 • 5 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 906 回帖 • 198 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 543 关注