在调用本平台API的时候, 需要用client_id标明自己的身份, 根据调用方式不同, 有下面两种方法:
通过https调用Api. 因为https的数据在传输过程中会被加密. 无法被窃听, 所以传输的数据是不会泄露的.
因此我们可以放心大胆的在请求中直接传递密钥信息:
client_id | 应用的Key |
client_secret | key对应的secret |
形如
http://<platform-hosturl>/api/path/to/method?client_id=xxxx&client_secret=xxxxxx
访问非加密的http://地址, 需要对所有参数进行签名. 传递client_id与签名结果.
因为调用过程在技术上存在被窃听的可能, 我们不能直接在数据上传递client_secret. 因此我们需要用一种签名技术. 使得不传递密钥也能证实自己的身份.
client_id | 应用的Key |
sign_method | md5 |
sign_time | 当前时间戳 |
sign | SignToken, 下文详解 |
SignToken = md5(SignString).toUpper()
SignString = Join( [ClientSecret,Method,Path,headers,GetParams,PostParams,ClientSecret], '&' )
RFC 3986 section 2.3
有效字符 = 字母 / 数字 / "-" / "." / "_" / "~"
问: 为什么要传递sign_time.
答: 那是因为黑客因为无法获知密钥, 虽然无法调用其他API请求. 但是可以用重复发送同样的数据来让系统产生异常. 这个叫做"重放攻击". 通过sign_time, 我们可以判断如果超过时间, 重放就会失去效果.
问: 为什么签名算法要包含请求参数, 只是对secret进行md5不可以么?
答: 那样无法起到任何保护作用, 黑客只需要截取到sign, 就能发起任何接口任何参数的调用. 因此, 为了安全起见, 必须对所有调用的数据加入到签名运算中. 使得改变任何参数, 签名结果都会发生变化. 从而使攻击无法实现.
问: 为什么签名方式如此复杂. 某某平台只对POST请求进行签名即可.
答: 我们的后端Api多样性比较大, 可能有的参数通过header传递, 或者get/post混合传递, 则必须对所有请求进行签名.