查看他人数据接口的安全校验机制

  通常开放一个可以查看他人数据的接口是比较危险的,但是这方面的需求确实是有的,比如用户分享自己的个人主页,或者用户在某些排行榜里/成为公众人物后,别人可以通过点击用户头像查看他的主页,这时候后端接口要做的事情是,正确识别请求的来源,保证是来自于用户自己的分享、排行榜里的点击等等。

  一个常见的做法是在后端生成分享链接/排行榜列表时同时返回一个token —— 一个不可逆的摘要串,如 md5(uid + time + secret),把用户ID + 时间戳 + 密钥通过某种 hash 算法生成一个签名/token,然后前端请求时带上这个 token,由后端来进行验证(首先验证时间戳的有效期,然后验证 token 的正确性)。只要 secret 不泄露、hash 算法足够安全(不可逆、难穷举),那么这个验证机制就是比较安全的。

  但是这里有一个不太好的点,就是这个 token 和时间绑定在一起了,时间戳过期后 token 验证就会不通过,这时候反映到业务上就是直接报错或者其它柔性方式处理——可以让前端定时刷新token,以保证时间戳不会过期(但这样子定时的频率要控制好,过快会给服务端造成压力)。

  还有一个点,假如时间戳有效期设置得过长,那么攻击者就可以看到不该给他看的数据,比如一个定时更新的排行榜,可以查看出现在榜单上的用户的个人主页,不在榜单上的用户不能开放主页查看功能——即不能通过直接调用接口获取数据。这时候如果时间戳设置的过长,超过了榜单定时更新的频率,比如榜单10分钟更新一次,而时间戳有效期为20分钟,15分钟后用户A已经掉出榜外,此时其它用户是不能看到用户A的主页的,但是因为 token 还没有过期,后端接口校验通过,此时正常返回用户A的个人主页数据,那么这个行为就是非预期的,就造成了安全漏洞,如果排行榜每次变化都比较大,即每个人都曾上过排行榜,那么就可能让攻击者把所有人的数据都拉取下来,相当于拖库了。

  此时我想到的一种方案是,首先保持时间戳有效期和排行榜的更新频率一致,然后对于校验不通过的 token,有两种可能,一个是正常的时间戳过期,比如前端没有定时更新或者更新的频率不够快,用户打开排行榜页面放置一段时间,此时 token 就过期了;另一种可能就是恶意攻击,token 是攻击者随机构造的。此时后端接口可以这样做,获取用户此时的排名,如果在排行榜里就正常返回个人主页数据,否则报错,获取排名的性能需要考虑,如果太耗时的话就不能这样做,就要考虑别的方案了。

 

posted @ 2019-05-23 10:17  Newdawn_ALM  阅读(416)  评论(0编辑  收藏  举报