开放平台认证
最后更新于:2022-04-02 03:08:41
[TOC]
> [参考](https://www.jianshu.com/p/ad410836587a)
## AccessKey&SecretKey (开放平台)
### 请求身份
为开发者分配`AccessKey`(开发者标识,确保唯一,可由用户填入)和 SecretKey(由算法生成,需要足够复杂)
### 防止篡改
步骤
1. 按照请求参数名的字母升序排列非空请求参数(包含AccessKey),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA;
2. 在stringA最后拼接上Secretkey得到字符串stringSignTemp;
3. 对stringSignTemp进行MD5运算,并将得到的字符串所有字符转换为大写,得到sign值。
说明
* 请求携带参数**AccessKey**和**Sign**,只有拥有**合法的身份**AccessKey和正确的签名Sign才能放行。这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到SecretKey(**仅作本地加密使用,不参与网络传输**),无法伪造合法的请求
### 重放攻击(可选,推荐)
timestamp+nonce方案
timestamp:生成当前时间戳
nonce:生成唯一标识符
服务器判断在timestamp的 15分钟内,是否存在nonce,存在则拒绝,不存在则通过,并记录 nonce(可以使用redis的expire,新增nonce的同时设置它的超时失效时间为15分钟
### 实现
`请求接口:http://api.test.com/test?name=hello&home=world&work=java`
#### 客户端
1. 生成当前时间戳`timestamp=now`和唯一随机字符串`nonce=random`
2. 按照请求参数名的字母**升序排列非空**请求参数(包含AccessKey)
`stringA="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random";`
3. 拼接密钥SecretKey
`stringSignTemp="stringA&SecretKey=secret";`
4. MD5并转换为大写
`sign=MD5(stringSignTemp).toUpperCase();`
5. 最终请求
`http://api.test.com/test?name=hello&home=world&work=java×tamp=now&nonce=nonce&sign=sign;`
#### 服务端
1. 是否包含 timestamp , nonce , AccessKey , sign
2. 是否满足 timestamp - now < timeout
3. 验证签名 Sign 是否正确
4. 查询 AccessKey 是否存在
5. 查看 nonce 是否存在,存在则报错,不存在则记录,并放行
';