一、概述
API网关是物联网平台面向开发者接口定义转发的服务,提供接口为Restful风格的HTTP接口。
HTTP Request以及Response都采用JSON格式字符串作为消息实体。
注意:文件上传或其他流式数据传输另作讨论。
采用HTTP协议的GET、POST、PUT、DELETE Method作为资源操作动作。操作原则为:
- GET:进行数据获取,当url有参数时,需要URLEncode后方可传输;
- POST:数据添加或者是复杂的数据查询,需要以Request Body作为查询参数的;
- PUT:数据修改;
- DELETE:数据删除;
术语
- 前端API:在API网关管理台创建定义,指定API的地址/方法/参数/认证方式等,为前后端开发进行对接而服务,前端API必须引用后端API才能实现具体的接口功能
- 后端API:后端服务注册进入平台,前端API必须引用后端API才能实现具体的接口功能
- 应用:利用应用的标识和秘钥进行签名作为访问前端API的一种方式,动态实现前端API授权的管控
- B端凭证:企业成员登录后换取的调用凭证
- C端凭证:企业用户登录后换取的调用凭证
二、针对对象
- 前端开发工程师,使用API网关定义好的前端API进行前端产品开发
- 后端开发工程师,使用API网关定义好的前端API进行二次开发以及接口聚合
- 技术经理/架构师,了解API网关运行原理机制从而进行技术方案评估
三、使用场景
- 使用API网关定义好的前端API进行前端产品开发
- 使用API网关定义好的前端API进行二次开发以及接口聚合从而实现云云对接等类似场景
- 使用API网关支持的认证功能为后端服务提供安全校验
- 使用API网关支持的流量控制功能为后端服务提供平滑流量控制
- 使用API网关支持的访问控制功能为后端服务提供访问来源黑白名单限制
四、协议设计
4.1 URL
请求协议://访问域名/接口版本/API接口路径
4.2 请求协议
HTTPS 1.1
- 推荐 HTTP 1.1
- 注意:HTTPS暂不需要使用证书双向认证。
4.3 访问域名
api.domain.com
- 注意:以最终定义域名为准。
4.4 接口路径
/v1/corp
- 注意:接口路径的第一个字段统一为接口版本。
- 完整地址示例:https://api.domain.com/v1/corp
五、请求鉴权
5.1 鉴权信息说明
HTTP请求API必须带上鉴权信息,平台通过鉴权信息来决定该请求能访问API范围以及数据范围。
鉴权机制有两种,以具体的API以及业务为准
鉴权方式 | 适用范围 | 说明 |
---|---|---|
AccessToken机制 | Web/App端管理平台API | 鉴权信息存入HTTP Header字段为:“Access-Token” |
Signature机制 | SaaS服务云云对接 | 鉴权信息存入HTTP Header字段为:“Signature” |
5.2 鉴权信息类型
- 注意:Access-Token为API网关北向应用调用时所需要传递的参数,但是SaaS应用本身设计API接口时,无需加入Access-Token字段。
- 鉴权信息优先以AccessToken为准,即是在请求头发现Access-Token标识会进入Access-Token的鉴权逻辑,仅在请求头未发现Access-Token标识且发现Signature标识才会进入Signature鉴权逻辑。
- 针对AccessToken鉴权机制和Signature机制鉴权机制,请求所需传的鉴权信息主要分为一下三种类型,不同的类型所能访问的权限结构不同,具体类型说明如下:
序号 | 类型 | 鉴权机制 | 获取方式 | 权限概述 |
---|---|---|---|---|
1 | Corp | [见 企业登录验证](../3)Open API/2)基础服务/2)成员管理/1)企业成员登录.md) | AccessToken机制 | 企业B端用户权限,主要用于管理台访问平台数据,包括不限于创建获取设备数据等 |
2 | User | 见 用户登录验证 | AccessToken机制 | 企业C端用户权限,主要用于C端APP访问平台数据,包括不限于订阅设备、获取个人信息等 |
3 | App | 见 应用网关登录验证 | Signature机制 | 应用网关权限,主要用于平台对接时,访问平台数据,可限制具体接口,包括不限于用户管理类数据、产品设备管理类数据等 |
5.3 鉴权信息处理
5.3.1 鉴权信息处理
- 通过API网关访问SaaS接口,API网关会承载授权认证以及API权限过滤。
- 通过API网关授权通过的接口,下发到Saas后,SaaS服务无需处理AccessToken认证以及App签名认证。
5.3.2 鉴权信息解析透传
- HTTP请求进入网关Gateway Server,网关会根据AccessToken或者Signature解析出请求对象的基本信息,优先以AccessToken为准,即是在请求头有Access-Token标识会进入Access-Token的鉴权逻辑
- 网关解析出AccessToken或者Signature的基本信息后封装成Request-Base请求头透传至后端服务,Request-Base为Base64字符串
- Base64之前的Request-Base内容格式为
{
"id": "请求对象标识",
"type": "请求对象类型",
"corp_id": "请求对象所属企业",
"name": "请求对象名称"
}
名称 | 必填 | 类型 | 备注 |
---|---|---|---|
id | TRUE | String | 请求对象标识,根据type不同而不同 1:应用APP标识 2:B端用户标识 3:C端用户标识 |
type | TRUE | Int | 请求对象类型 1:应用APP类型 2:B端用户 3:C端用户 |
corp_id | TRUE | String | 请求对象所属企业 |
name | TRUE | String | 请求对象名称 |
5.4 Signature机制签名算法
5.4.1 签名依赖元素
- Header
- App-ID
- Timestamp
- Request-ID
- Content-MD5
- FullPath = Path + Query
- 格式为:
/v2/devices/filter/configs?name=xlink
- 格式为:
- Body
- 用于生成Header中的Content-MD5, 若无Body则不用该操作
String Content-MD5 = Base64.encodeBase64(MD5(body.getbytes("UTF-8")));
- 用于生成Header中的Content-MD5, 若无Body则不用该操作
5.4.2 签名过程
- 构造签名字符串, 若无Content-MD5则可以不传
SignToString = APP-ID + "\n" + App-Secret + "\n" + Timestamp + "\n" + Request-ID + "\n" + FullPath + "\n" + Content-MD5
- 签名
Base64.encodeBase64(SHA256(SignToString))
5.4.3 AppId、AppSecret的获取
- AppId、AppSecret在企业管理平台的API网关服务中,由IT人员或开发人员统一颁布。
六、请求头
- 根据不同的鉴权机制所需传输的请求头有所不同
6.1 AccessToken机制
字段 | 说明 | 是否必须 |
---|---|---|
Group | 前端API标识 | 是 |
Stage | 前端API所属环境, RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 | 是 |
Content-Type | application/json | 是 |
Access-Token | 调用凭证,一般为用户登录后平台下发的用户Token | 否,以具体接口为准 |
Request-Base | API网关解析Token后加入到Header中的基础字段 | 否,请求通过API网关后自动加入 |
6.2 Signature机制
字段 | 说明 | 必填 |
---|---|---|
Group | 前端API标识 | true |
Stage | 前端API所属环境 RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 |
true |
Content-Type | application/json | true |
Signature | 签名 | true |
App-ID | 应用标识 | true |
Timestamp | 时间戳 | true |
Request-ID | 请求标识 | true |
Content-MD5 | 请求内容MD5散列值 | false 当请求为POST和PUT请求时必传 |
七、通用返回结果
{
"code": 4081001,
"status": 408,
"msg": "Request Timeout",
"data": {
"name":"xlink"
}
}
名称 | 必填 | 类型 | 备注 |
---|---|---|---|
code | True | Long | 业务错误码,业务错误码由各个接口来具体定义。200代表成功,其他代表失败。业务错误码见下方示例以及分段说明 |
status | False | Int | 通用HTTP状态码,200表示执行成功。其他表示错误或其他返回,看附录的HTTP状态码定义。 |
msg | True | String | 错误的详细信息描述。请求错误时存在;否则为”” 空字符。 |
data | True | Object | 具体的接口响应数据。无实际响应数据时,该字段为空对象{}。其他数据以具体接口为准。 |
八、错误码定义
8.1 HTTP状态码(status)
值 | 描述 |
---|---|
200 | 请求成功 |
302 | 重定向跳转 |
400 | 请求字段不合法 |
401 | 缺少调用凭证 |
403 | 授权不通过 |
404 | 资源不存在 |
408 | 请求超时 |
405 | 方法不支持 |
502 | 响应超时 |
503 | 参数解析错误 |
504 | 服务器异常 |
九、示例
- 由于API网关支持三种不同的认证方式,因此分三种情况进行示例,具体如下:
9.1 B端认证示例
9.1.1 获取Access-Token
9.1.1.1 Request
- URI
/v2/corp_auth
- HOST
https://api.domain.com
- Method
POST
- Header
名称 | 值 | 必填 |
---|---|---|
Content-Type | application/json | true |
- Body
{
"account": "demo@xlink.cn",
"password": "Test123456"
}
名称 | 位置 | 必填 | 类型 | 备注 |
---|---|---|---|---|
account | body | true | String | 企业成员账号 |
password | body | true | String | 企业成员密码 |
9.1.1.2 Response
- Body
{
"member_id": "1207d2ad165a7001",
"access_token": "QkIzNUM2NERCOTNGCRUU0NUVGQjFCMDhBOTA4NEZBMjlDQzI0MDlDQTBCNzAwOA==",
"refresh_token": "NjY3OTZDM0E3RkE0MjNGN0MwQzUxQkYzRTJDMjZGODc2RkI3MUQzOTkyRjUxNw==",
"role_type": 0,
"expire_in": 7200,
"corp_id": "1007d2ad165a7000"
}
名称 | 必填 | 类型 | 描述 |
---|---|---|---|
corp_id | true | String | 企业标识 |
member_id | true | String | 企业成员标识 |
access_token | true | String | 调用凭证 |
refresh_token | true | String | 刷新凭证 |
expire_in | true | Int | 调用凭证过期时长 |
9.1.2 发起调用
9.1.2.1 Request
- URI
/v2/api-gateway/demo
- HOST
https://api.domain.com
- Method
POST
- Header
名称 | 值 | 必填 |
---|---|---|
Content-Type | application/json | true |
Access-Token | 调用凭证 | true, 9.1.1获取到的B端access_token |
Group | 前端API标识 | true |
Stage | 前端API所属环境 RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 |
true |
- Body
{
"name": "xlink",
"age": 19
}
名称 | 位置 | 必填 | 类型 | 备注 |
---|---|---|---|---|
name | body | true | String | 名称 |
age | body | true | Int | 年龄 |
9.1.2.2 Response
- Body
{
"code": 200,
"status": 200,
"msg": "",
"data": {
"age": 19,
"name": "xlink"
}
}
字段 | 必填 | 类型 | 备注 |
---|---|---|---|
code | true | Long | HTTP状态码 |
status | false | Int | 业务错误码 |
msg | true | String | 业务错误信息 |
data | true | Object | 业务数据 |
data.age | true | Int | 年龄 |
data.name | true | String | 名词 |
9.2 C端认证示例
9.2.1 获取Access-Token
9.2.1.1 Request
- URI
/v2/user_auth
- HOST
https://api.domain.com
- Method
POST
- Header
名称 | 值 | 必填 |
---|---|---|
Content-Type | application/json | true |
- Body
{
"corp_id": "1207d2ad165a7001",
"phone": "13838383388",
"phone_zone": "+86",
"password": "Test123465",
"resource": "Test",
"email": "liqinghua@xlink.cn"
}
字段 | 位置 | 必填 | 类型 | 备注 |
---|---|---|---|---|
corp_id | body | true | String | 企业标识 |
phone | body | false | String | 用户手机号,与用户邮箱二选一 |
phone_zone | body | true | String | 用户手机区号 |
password | body | true | String | 用户密码 |
resource | body | false | String | 用户登录源 |
body | false | String | 用户邮箱,与用户手机号二选一 |
9.2.1.2 Response
- Body
{
"user_id": 4452451254,
"access_token": "QkIzNUM2NERCOTNGCRUU0NUVGQjFCMDhBOTA4NEZBMjlDQzI0MDlDQTBCNzAwOA==",
"refresh_token": "NjY3OTZDM0E3RkE0MjNGN0MwQzUxQkYzRTJDMjZGODc2RkI3MUQzOTkyRjUxNw==",
"expire_in": 7200
}
字段 | 必填 | 类型 | 备注 |
---|---|---|---|
user_id | true | Int | 用户标识 |
access_token | true | String | 调用凭证 |
refresh_token | true | String | 刷新凭证 |
expire_in | true | Int | 调用凭证过期时长 |
9.2.2 发起调用
9.2.2.1 Request
- URI
/v2/api-gateway/demo
- HOST
https://api.domain.com
- Method
POST
- Header
字段 | 值 | 必填 |
---|---|---|
Content-Type | application/json | true |
Access-Token | 调用凭证 | true, 9.2.1获取到的C端access_token |
Group | 前端API标识 | true |
Stage | 前端API所属环境 RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 |
true |
- Body
{
"name": "xlink",
"age": 19
}
名称 | 位置 | 必填 | 类型 | 备注 |
---|---|---|---|---|
name | body | true | String | 名称 |
age | body | true | Int | 年龄 |
9.2.2.2 Response
- Body
{
"code": 200,
"status": 200,
"msg": "",
"data": {
"age": 19,
"name": "xlink"
}
}
字段 | 必填 | 类型 | 备注 |
---|---|---|---|
code | true | Long | HTTP状态码 |
status | false | Int | 业务错误码 |
msg | true | String | 业务错误信息 |
data | true | Object | 业务数据 |
data.age | true | Int | 年龄 |
data.name | true | String | 名词 |
9.3 App认证示例
9.3.1 构建签名
- 参考 5.4 Signature机制签名算法
9.3.2 Restful发起调用
9.3.2.1 Request
- URI
/v2/api-gateway/demo
- HOST
API网关域名, 非中台API域名
- Method
POST
- Header
名称 | 值 | 必填 |
---|---|---|
Content-Type | application/json | true |
Group | 前端API标识 | true |
Stage | 前端API所属环境 RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 |
true |
Content-Type | application/json | true |
Signature | 签名 | true |
App-ID | 应用标识 | true |
Timestamp | 时间戳 | true |
Request-ID | 请求标识 | true |
Content-MD5 | 请求内容MD5散列值 | false 当请求为POST和PUT请求时必传 |
- Body
{
"name": "xlink",
"age": 19
}
名称 | 位置 | 必填 | 类型 | 备注 |
---|---|---|---|---|
name | body | true | String | 名称 |
age | body | true | Int | 年龄 |
9.3.2.2 Response
- Body
{
"code": 200,
"status": 200,
"msg": "",
"data": {
"age": 19,
"name": "xlink"
}
}
字段 | 必填 | 类型 | 备注 |
---|---|---|---|
code | true | Long | HTTP状态码 |
status | false | Int | 业务错误码 |
msg | true | String | 业务错误信息 |
data | true | Object | 业务数据 |
data.age | true | Int | 年龄 |
data.name | true | String | 名词 |