api协议
在调用本平台API的时候, 需要用app_key标明自己的身份, 根据调用方式不同, 有下面两种方法:
A. 首选方案:
通过https调用Api. 因为https的数据在传输过程中会被加密. 无法被窃听, 所以传输的数据是不会泄露的. 因此我们可以放心大胆的在请求中直接传递密钥信息:
形如
https://apigateway.shopex.cn/router?method=shopex.queue.read&app_key=xxxx&client_secret=xxxxxx
B. 备选方案
访问非加密的http://地址, 需要对所有参数进行签名. 传递app_key与签名结果. 因为调用过程在技术上存在被窃听的可能, 我们不能直接在数据上传递client_secret. 因此我们需要用一种签名技术. 使得不传递密钥也能证实自己的身份.
SignToken = md5(SignString).toUpper()
SignString = Join( [ClientSecret,Method,Path,headers,GetParams,PostParams,ClientSecret], '&' )
原理解答 问: 为什么要传递sign_time. 答: 那是因为黑客因为无法获知密钥, 虽然无法调用其他API请求. 但是可以用重复发送同样的数据来让系统产生异常. 这个叫做"重放攻击". 通过sign_time, 我们可以判断如果超过时间, 重放就会失去效果. 问: 为什么签名算法要包含请求参数, 只是对secret进行md5不可以么? 答: 那样无法起到任何保护作用, 黑客只需要截取到sign, 就能发起任何接口任何参数的调用. 因此, 为了安全起见, 必须对所有调用的数据加入到签名运算中. 使得改变任何参数, 签名结果都会发生变化. 从而使攻击无法实现. 问: 为什么签名方式如此复杂. 某某平台只对POST请求进行签名即可. 答: 我们的后端Api多样性比较大, 可能有的参数通过header传递, 或者get/post混合传递, 则必须对所有请求进行签名.
通过https调用Api. 因为https的数据在传输过程中会被加密. 无法被窃听, 所以传输的数据是不会泄露的. 因此我们可以放心大胆的在请求中直接传递密钥信息:
| app_key | 应用的Key |
| client_secret | key对应的secret |
访问非加密的http://地址, 需要对所有参数进行签名. 传递app_key与签名结果. 因为调用过程在技术上存在被窃听的可能, 我们不能直接在数据上传递client_secret. 因此我们需要用一种签名技术. 使得不传递密钥也能证实自己的身份.
| app_key | 应用的Key |
| sign_method | md5 |
| sign_time | 当前时间戳 |
| sign | SignToken, 下文详解 |
- Method = GET | POST
- Path = /path/to/method
- headers = urnencode(HeaderKey1 + HeaderValue1 + HeaderKey2 + HeaderValue2 ...)
- GetParams = urnencode(GetKey1=GetValue1&GetKey2=GetValue2 ...)
- PostParams = urnencode(PostKey1=PostValue1&PostKey2=PostValue2 ...)
- ClientSecret = key的Secret密钥
- 其中headers, GetParams, PostParams需要首先对key进行a-z排序.
- 不是所有的header参数需要签名, 只对X-Api-开头以及Authorization进行签名
- signtoken是大写
- "!" -> %21
- "*" -> %2A
- "(" -> %28
- ")" -> %29
- " " -> %20
function sort_obj(object){
var ks = Object.keys(object);//对参数进行a-z排序
ks.sort();
var d = [];
for(i=0;i<ks.length;i++){
d.push( ks[i] + "=" + object[ks[i]] );
}
return encodeURIComponent(d.join("&"));//d.join("&")==>debug=true&name=zhangsan&read=true
}
function sign(method, path, headers, GetParam, PostParam, secret){
var d = [];
d.push(secret);
d.push(method);
d.push(encodeURIComponent(path));
d.push(sort_obj(headers));
d.push(sort_obj(GetParam));
d.push(sort_obj(PostParam));
d.push(secret);
signstr = d.join("&");//拼接参数,结果:xxx&method=shopex.queue.read&getparam=xxx&postparam=xxx&xxx
return md5(signstr).toUpperCase();
}
原理解答 问: 为什么要传递sign_time. 答: 那是因为黑客因为无法获知密钥, 虽然无法调用其他API请求. 但是可以用重复发送同样的数据来让系统产生异常. 这个叫做"重放攻击". 通过sign_time, 我们可以判断如果超过时间, 重放就会失去效果. 问: 为什么签名算法要包含请求参数, 只是对secret进行md5不可以么? 答: 那样无法起到任何保护作用, 黑客只需要截取到sign, 就能发起任何接口任何参数的调用. 因此, 为了安全起见, 必须对所有调用的数据加入到签名运算中. 使得改变任何参数, 签名结果都会发生变化. 从而使攻击无法实现. 问: 为什么签名方式如此复杂. 某某平台只对POST请求进行签名即可. 答: 我们的后端Api多样性比较大, 可能有的参数通过header传递, 或者get/post混合传递, 则必须对所有请求进行签名.