[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&timestamp=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&timestamp=now&nonce=nonce&sign=sign;` #### 服务端 1. 是否包含 timestamp , nonce , AccessKey , sign 2. 是否满足 timestamp - now < timeout 3. 验证签名 Sign 是否正确 4. 查询 AccessKey 是否存在 5. 查看 nonce 是否存在,存在则报错,不存在则记录,并放行