接口平安问题
- 申请身份是否非法?
- 申请参数是否被篡改?
- 申请是否惟一?
AccessKey&SecretKey(开放平台)
申请身份
为开发者调配AccessKey(开发者标识,确保惟一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜想)。
避免篡改
参数签名
- 依照申请参数名的字母升序排列非空申请参数(蕴含 AccessKey),应用 URL 键值对的格局(即 key1=value1&key2=value2…)拼接成字符串 stringA;
- 在 stringA 最初拼接上 Secretkey 失去字符串 stringSignTemp;
- 对 stringSignTemp 进行 MD5 运算,并将失去的字符串所有字符转换为大写,失去 sign 值。
申请携带参数 AccessKey 和Sign,只有领有非法的身份 AccessKey 和正确的签名 Sign 能力放行。这样就解决了身份验证和参数篡改问题,即便申请参数被劫持,因为获取不到 SecretKey(仅作本地加密应用,不参加网络传输),无奈伪造非法的申请。
重放攻打
尽管解决了申请参数被篡改的隐患,然而还存在着重复使用申请参数伪造二次申请的隐患。
timestamp+nonce 计划
nonce 指 惟一的随机字符串,用来标识每个被签名的申请。通过为每个申请提供一个惟一的标识符,服务器可能避免申请被屡次应用(记录所有用过的 nonce 以阻止它们被二次应用)。
然而,对服务器来说永恒存储所有接管到的 nonce 的代价是十分大的。能够应用timestamp 来优化 nonce 的存储。
假如容许客户端和服务端最多能存在 15 分钟的时间差,同时追踪记录在服务端的 nonce 汇合。当有新的申请进入时,首先查看携带的 timestamp 是否在 15 分钟内,如超出工夫范畴,则回绝,而后查问携带的 nonce,如存在已有汇合,则回绝。否则,记录该 nonce,并删除汇合内工夫戳大于 15 分钟的 nonce(能够应用 redis 的 expire,新增 nonce 的同时设置它的超时生效工夫为 15 分钟)。
实现
申请接口:http://api.test.com/test?name…
-
客户端
- 生成以后工夫戳 timestamp=now 和惟一随机字符串 nonce=random
- 依照申请参数名的字母升序排列非空申请参数(蕴含 AccessKey)
stringA="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random";
- 拼接密钥 SecretKey
stringSignTemp="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random&SecretKey=secret";
- MD5 并转换为大写
sign=MD5(stringSignTemp).toUpperCase();
- 最终申请
http://api.test.com/test?name=hello&home=world&work=java×tamp=now&nonce=nonce&sign=sign;
- 服务端
Token&AppKey(APP)
在 APP 凋谢 API 接口的设计中,因为大多数接口波及到用户的个人信息以及产品的敏感数据,所以要对这些接口进行身份验证,为了平安起见让用户裸露的明文明码次数越少越好,然而客户端与服务器的交互在申请之间是无状态的,也就是说,当波及到用户状态时,每次申请都要带上身份验证信息。
Token 身份验证
- 用户登录向服务器提供认证信息(如账号和明码),服务器验证胜利后 返回 Token给客户端;
- 客户端将 Token 保留在本地,后续发动申请时,携带此 Token;
- 服务器查看 Token 的有效性,无效则放行,有效(Token 谬误或过期)则回绝。
安全隐患:Token 被劫持,伪造申请和篡改参数。
Token+AppKey 签名验证
与下面开发平台的验证形式相似,为客户端调配 AppKey(密钥,用于接口加密,不参加传输),将 AppKey 和所有申请参数组合成源串,依据 签名算法 生成签名值,发送申请时将签名值一起发送给服务器验证。这样,即便 Token 被劫持,对方不晓得 AppKey 和签名算法,就无奈伪造申请和篡改参数。再联合上述的 重发攻打 解决方案,即便申请参数被劫持也无奈伪造二次反复申请。
实现
登陆和退出申请
后续申请
- 客户端 和上述开放平台的客户端行为相似,把 AccessKey 改为 token 即可。
- 服务端