api协议

在调用本平台API的时候, 需要用app_key标明自己的身份, 根据调用方式不同, 有下面两种方法: A. 首选方案:
通过https调用Api. 因为https的数据在传输过程中会被加密. 无法被窃听, 所以传输的数据是不会泄露的. 因此我们可以放心大胆的在请求中直接传递密钥信息:
app_key 应用的Key
client_secret key对应的secret
形如 https://apigateway.shopex.cn/router?method=shopex.queue.read&app_key=xxxx&client_secret=xxxxxx B. 备选方案
访问非加密的http://地址, 需要对所有参数进行签名. 传递app_key与签名结果. 因为调用过程在技术上存在被窃听的可能, 我们不能直接在数据上传递client_secret. 因此我们需要用一种签名技术. 使得不传递密钥也能证实自己的身份.
app_key 应用的Key
sign_method md5
sign_time 当前时间戳
sign SignToken, 下文详解
SignToken = md5(SignString).toUpper() SignString = Join( [ClientSecret,Method,Path,headers,GetParams,PostParams,ClientSecret], '&' )
  • 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是大写
urlencode规则: RFC 3986 section 2.3 有效字符 = 字母 / 数字 / "-" / "." / "_" / "~"
  • "!" -> %21
  • "*" -> %2A
  • "(" -> %28
  • ")" -> %29
  • " " -> %20
js代码样例
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混合传递, 则必须对所有请求进行签名.