继续 贴一篇之前工作中的经验案例
AK/SK简单实战
项目中,平台需要上下级级联传输数据,发起请求时,需要进行安全认证,最终的认证方案 设计如下。
1 基本概念
APP ID :用户id, 会在网络传输中出现,(因为域管设计的是http请求,所以容易暴露),用于识别用户身份。每个域管都有个全局唯一标识码-indexCode,使用此标识作为APP ID。
APP key : 用户的key, 可以有多个,每个key对应一组权限,边缘域的API代理不需做权限细分,所以此处APP ID = APP key。
APP Secret: 用户的秘钥,支持重置,要保证不容易被穷举,生成算法不容易被猜到,禁止在网络上传输,用户需要妥善保存,防止被窃,否则有泄密风险。目前简化设计,同一域管下所有用户使用相同的key, 不同域管使用不同的key, key一旦被重置,之前的key就会失效。
token : 在使用ak/sk 登陆认证通过后,返回token 给客户端,token有有效期限制,有效期内直接使用token调用接口即可,当请求量非常大时,能有效降低服务器压力。因为域管设计的是http请求,容易暴露token, 且目前请求量不大,所以这里不用token。
2 上下级级联配置
APP ID = APP key=域管全局唯一标识码-indexCode 是上级域管的固定值,一个随机生成的32位uuid,生成后不再改变。
APP Secret 需要由下级生成,拷贝配置到上级。下级若重置了secret, 上级需要重新配置,否则无法访问下级数据。
3 通讯协议
u HTTP请求头需指定Content-Type:application/json。
u 字符编码:utf-8
u HTTP请求参数(GET时放在querystring中,POST时放置在body 的json中)必选参数:
参数名 |
类型 |
描述 |
ts |
long |
进行接口调用时的时间戳,即当前时间戳 (时间戳:当前距离Epoch(1970年1月1日) 以秒计算的时间,即unix-timestamp),服务端会校验时间戳,例如时间差超过20分钟则认为请求无效,防止重复请求的攻击 |
nonce |
long |
随机数,与ts相配合,以保证每次请求生成的签名都不一样 |
appid |
string |
域管全局唯一标识码-indexCode,用于标识哪个域管发来的请求 |
u HTTP 请求头必须加上Authorization字段,字段内容为签名(其中“Sign ”是 值):
Authorization:Sign bhCQXTVyfj5cmA9uKkPFx1zeOXM=
² 签名计算方法:
GET请求POST请求::
待签名串为整个url参数:ts=1374908054&nonce=4587954&appid=xxxxx¶m=xxxx
计算签名:
使用HMAC-SHA256签名算法,将app secret作为算法的key,生成待签名串的签名。
将得到的签名BASE64编码后设置到Authorization头中(其中“Sign ”是 值):
Authorization:Sign bhCQXTVyfj5cmA9uKkPFx1zeOXM=
4 签名校验
下级域(服务器)收到上级域(客户端)的请求后,使用自身的app secret ,按上述签名计算方法,计算出签名, 与Authorization 中的签名值比对,
相同则认为请求合法,转发请求并返回响应数据,不同则认为非法,返回error
1.1.1.2 PD-022-002 域配置
实现下级域的添加、删除、修改操作,所有下级域存储在一张表中;
支持生成/重置本级域密钥,密钥加密存储在db中。
秘钥约定:32位随机UUID,秘钥一旦重置,之前的秘钥将无效。