Bootstrap

APP 防重放实现

API 重放攻击又称为回放攻击,它会不断的、恶意的重复一个有效的请求,虽然现在有 https 但是 https 是数据加密,却阻止不了防重放攻击,因为攻击者只要盗取到你的 API 请求,不需要去解密数据。这在 app 端更为常见,因为 web 端会有 token 校验等实现,而一些 app 端请求后端请求无法做 token 校验。

那么如何防止防重放呢?最常用的方式就是签名。

签名算法

签名一般分为签名和校验两个步骤:

每次请求调用方除了携带正常的请求参数和 header 还需要携带一些用于签名的 header, 常见的有:

X-App-Versionapp 版本

X-Device-Idapp    设备 id

X-Platforma    app 设备类型

X-Timestampunix    时间戳 (秒) 时间戳与服务器时间戳相差超过一定时间(60s) 则会失败

X-App-Key业务申请,服务端下发,需要保存在数据库内,客户端切记不能泄露,每一个 appkey 对应一个 appSecret

X-Nonce       随机数,确保在过期时间内,nonce 不会重复。可以用 md5(uuid+timestamp)等算法。

X-Signature      客户端签名结果no

Content-Typeapplication/josn, application/x-www-form-urlencoded

用于签名的字符串:

签名字符串:
X-Device-Id+X-App-Version+X-Platform+x-Nonce+$RequestMethod+$RequestPath+$RequestArgs+$Body+X-App-Key+X-Timestamp

其中:
X-APP-Key: 调用方向被调方申请得到。

RequestMethod: 请求方法

RequestPath: 请求路径,比如 /v1/query

Body: 请求体,其中对于 json 和 form 格式会做不同的处理。对于 application/json 则直接将整个 json 串 base64 字符串。对于application/x-www-form-urlencoded 则首先要将 formData key=value 值按照 key 进行升序排序,按照 key1=value1&key2=value2 方式拼接

RequestArgs: 将 queryArgs key=value 值按照 key 进行升序排序,按照 key1=value1&key2=value2 方式拼接。

得到签名字符串后,用 hmacsha256 进行签名。其中 secret 为调用方向被调方申请得到,同样不能泄露。

得到签名字符串,将签名结果放入 header X-Signature 内发送请求即可。

服务端验签具体步骤

服务端获得请求做如下验签动作:假设过期时间为 60s。

防重放原理

首先是安全性,由 appKey 与 appSecret 保证,由于 appSecret 不会在网络中传播,所以丢失风险很小。

其次是怎么防重放,将时间戳放入签名内,可以限制签名有效期,即使被劫持,也只能在有效期内进行,无法跨域很长时间进行。利用 nonce 就可以彻底防止防重放了,因为 nonce 生成是在过期时间内确保唯一的。所以每次请求都会不一样。每次请求都会校验 nonce 是否已经使用过。如果使用过就可以认为是一个重放请求,直接拦截在网关层。