Linx's Solution

带时间戳Hash,实现一段时间内哈希值不变

简单的api校验

  • 服务端维护并提供 ApiKey ApiSecret
  • sign=hash(<ApiKey><params><timestamp><ApiSecret>) 方式生成签名,然后将ApiKey和timestamp以及签名放到Header或者Query里传给服务端
  • 服务端校验header里的时间戳是否太旧,太旧则表示该请求已经过期,需要重新签名
  • 服务端根据ApiKey到数据库查询到ApiSecret,按照同样的规则,把客户端传来的时间戳作为时间戳,进行签名,如果签名结果和传过来的签名相同则签名通过,否则401

说明:

  • ApiSecret没有在请求中传输,可以保证即使被抓包,也一般不能生成正确的签名(一般来说,怂一点)
  • 由于会校验时间戳,那么即使被抓包,那同样的请求并不能再次发送到服务端,因为请求有有效期了,可以一定程度上防止重放攻击(如果客户端和服务端的时间一致,那么可以将过期时间设置的很短)
  • 更严格点,可以把签名放到redis,这样一个签名只能请求一次
  • 待签名内容需要有参数的部分在内,否则如果请求被拦截,然后篡改请求参数,那也是种攻击

hash+timestamp

  • 和前面的类似,只不过时间戳在被签名时不直接拼接,而是使用 timestamp/30,即整除30,那么三十秒内,整除的结果的整数部分是一样的,也就是说30秒内同样的参数,生成的签名是一样的. 例如 165355314430 = 55118438.13333333 165355314830=55118438.266666666
  • 这时候如果客户端和服务端之间有几秒的时间差,那么服务器可以把当前时间戳往前退30秒或者往后推30秒,再整除30,也可以让验证通过