sdkapi 接口架构设计
背景:
最近和公司的同事一起做了一个项目,主要是把公司里的一些东西做成接口,供第三方手机APP来调用。这个接口要做成通用的。任何第三方都可以
来调用。而且要保证第三方有权限来调用这些接口、能调用这些接口中的哪些接口以及用户身份认证。最后讨论决定用RESTful API。目前在三种
主流的web服务实现方案中,REST模式服务相比复杂的SOAP和XML-RPC对比来讲,更加简洁,越来越多的WEB服务开始使用REST设计并实现。但其缺少
安全特性。为了解决这个缺少安全特性,请看下面。
REST API简介
REST是无状态传输,无需session,所以每次请求都得带上身份认证信息。REST是基于http协议。它的安全特性需要我们自己来实现。RESTful web
services概念的核心就是”资源”。资源可以用URI来表示。客户端使用HTTP协议订阅的方法来发送请求到这些URIS
HTTP方法 行为 实例
GET 获取资源的信息 http://xx.com/api/orders
GET 获取某个特定资源的信息 http://xx.com/api/orders/123
POST 创建新资源 http://xx.com/api/orders
PUT 更新资源 http://xx.com/api/orders/123
DELETE 删除资源 http://xx.com/api/orders/123
对于请求的数据一般用json。
身份认证
身份认证包含很多种,有HTTP Basic,APIkey Oauth等,下面简单介绍一下:
HTTP Basic
REST由于是无状态传输,所以每一次请求都得带上身份认证信息,第一种身份认证就是http basic。这种方式在客户端要求简单。在服务端实现
也很简单,只需要配置apache等web服务器即可实现,所以对于简单的服务来说还是挺方便的。但是这种方式安全性较低,就是简单的将用户名和
密码base64编码放到header中。
base64编码前: Basic admin:admin base64编码后: Basic YWRtaW46YWRtaW4= 放到Header中:
Authorization: Basic YWRtaW46YWRtaW4=
正是因为是简单的base64编码存储,切记在这种方式下一定要使用SSL,不然就裸奔了。API KEY
API Key就是经过用户身份认证之后服务端给客户端分配一个API Key。流程如下:
client端向服务端注册,服务端给客户端发送响应的api_key以及security_key,这个是一一对应的。注意保存不要泄露,然后客户端根据
api_key,security_key,timestrap,rest_url(请求路径)采用hmacsha256算法得到一个hash值sign,构造URL发送到服务端。服务端收到该请求
后,首先验证api_key是否存在,存在则获取该api_key对应的security_key。接着验证timestrap是否超过时间限制,可依据系统而定。这样
就防止部分重放攻击,获取rest_url来计算sign。之后和url中的sign值做校验。这样的设计就防止了数据被篡改。
client:
api_key,security_key,timestrap,rest_url ——->sign
/rest/v1/interface/eth0/?api_key=jdfkla132×trap=14232423423423&sign=13sdfsdfsdsd
server:
/rest/v1/interface/eth0/?api_key=jdfkla132×trap=14232423423423&sign=13sdfsdfsdsd ----->api_key,timestrap,rest_url,sign
api_key--->security_key
api_key,security_key,timestrap,rest_url ------->sign
sign <---> sign
Oauth2
腾讯QQ第三方登录。
我们现在所实现是:
APP认证,接口认证。身份认证。使用过滤器Filter来实现。
SDK-API系统为对接App分配appId和appSecret
下面参数,每次访问的时候必须放在HTTP Header部分。
X-Security:APP认证,所有的api请求均要带上次参数。
X-Security=(appId + “:” + currentTimestampInMillis +”:” + checkSum) checkSum = HexString(MD5Hash(appId + “:”+
currentTimestampInMillis + “:” +appSecret))。
X-Security例子:iHGWFNWR23:1412342342342:5454c3345sdf323sdfsf3
服务器端获取到X-Security之后,先判断是否为null,然后通过appid来获取appSecret来判断appId是否有效。然后根据currentTimestampInMillis
来判断时间是否过期。然后判断传过来的checkSum和自己算出来的是否一致。如果一致就APP接口认证通过。
appId做接口认证。即有没有权限访问其中某一个接口。在服务端把每一个appId对应接口访问路径记录下来。
X-User-ID:用户登录之后xxxx分配的用户ID,非合作方ID。登录需要单独写个接口。
X-Token:登录成功之后分配的Access token。和X-User-ID配对使用。如果HTTP返回407错误,客户端必须对用户重新验证登录,重新分配Access token
X-UUID:为每一次API请求生成的唯一标识,用以跟踪数据。
解析:
当请求到达服务端的时候,APP认证和接口认证通过之后,就开始身份认证了。首先从请求中获取X-User-ID和X-Token。然后需要校验登录的
URL进行登录校验。注意:有一些接口是不需要校验登录的。比如:主播列表,排行榜等信息。因为X-User-ID和X-Token是我们分配给第三方的
所以我们自己就清楚该怎么校验了。
SDK API实现详解
我们使用swagger文档来生成spring boot框架的java代码。
swagger地址:editor.swagger.io/#/
下面有个登录接口。用于第三方登录来获取X-User-Id和X-Token。
api文档内容如下:
1 |
|