API防篡改

在设计API时,一直在想,如果被抓包了,修改数据,重新发送请求怎么办,今天脑补了一下。

重放攻击

我们在设计接口的时候,最担心一个接口被别有用心的用户截取后,用于重放攻击。重放攻击是什么呢?就是把请求被原封不动地重复发送,一次,两次...n次。这样可能导致:

  • 如果这个【后台逻辑】是插入数据库操作,就很容易造成多条重复的数据插入数据库。
  • 如果这个【后台逻辑】是查询数据库操作,就可能导致反复查询,数据库阻塞等情况。

如何防篡改和重放攻击呢?

客户端生成请求参数

来看看一个url:

http://www.xxxx.com?userId=123&userName=zhangsan×tamp=1480556543&nonce=43f34f33&sign=80b886d71449cb33355d017893720666&token=sdxxffstgccs

在这个链接中加入的timestamp、nonce、token和sign参数。

  • timestamp:获取请求的时间戳。
  • nonce: 随机串,比如 md5(timestamp+rand(0, 1000),正常情况下,在短时间内(比如60s)连续生成两个相同nonce的情况几乎为0。
  • token: 用户登录的令牌。
  • sign:sign根据请求的参数生成:
    a. 按照请求参数名称将所有请求参数按照字母先后顺序排序得到:keyvaluekeyvalue...keyvalue 字符串如:将userId=123,userName=zhangsan, 排序为: userId=123,userName=zhangsan,然后将参数名和参数值进行拼接得到参数字符串:userId123userNamezhangsan。
    b. 再拼接timestamp、nonce,进行md5加密,就生成了一个sign签名。

服务器端进行验证

  • 验证token,验证token是否存在,如果存在,则说明用户已经进行了登录验证,如果token不存在,则返回错误值。
  • 验证timestamp,这里是针对重放攻击的,通过验证timestamp,比较请求时间和当前时间,(假如我们定义这个请求在60s内有效),如果超过60s,则是无效的请求。
  • 验证nonce,验证完timestamp后,保证数据请求必须在60s内,那么,如何保证数据请求的唯一性呢?在每次请求成功时,我们会将nonce缓存起来(他的缓存有效期为60s),则可以通过比较,nonce是否在缓存中,来保证,在60s内是否,进行了重放攻击。
  • 验证sign签名:将获取到的参数,也按照sign的生成方式,生成一个新的sign,与请求中的sign进行比较,如果相等,则说明数据没有被篡改。

你可能感兴趣的:(API防篡改)