下午在谈交易类服务的时候,除了证书做数字签名以外,也谈到了重放攻击的问题。
对于重放攻击可以通过序列号的方式来判断。
序列号从颁发角度分成:1.服务调用者自身颁发。2.服务提供者颁发。
序列号生成方式分成两类:1.不重复,随机颁发。2.递增。3.时间戳。
颁发者如果选择是服务提供者,那么就会使得原本一次的会话交互变成两次,增加了复杂度和失败率,因此最好选择服务调用者自身颁发。生成方式如果选择1,那么存储的成本很大(服务调用者颁发的方式,在服务调用者这边必须全量保存,在服务提供者这边如果校验没有被使用过,也会记录下来,最终也是全量保存。服务提供者颁发方式,序列号只存储在服务提供者这边,不过也是全量。)生成方式选择2,那么不论选择哪一种颁发方式,都只需要保存上一次的序列号,但是对于多线程和集群的并发访问控制需要做好保护,防止由于并发访问本身顺序不准确导致服务被拒绝。生成方式选择3,那么任何一种颁发方式都不需要保持序列号,校验的时候制定容忍时间窗大小来判断是否是有效的时间戳。需要注意的是客户端和服务端的时间差异性问题,当时间差大于可容忍的时间窗,那么每次请求都可能被作为无效请求拒绝。
这里我的想法是结合两种方式去做重放攻击的防范,即保证资源使用的可控,也保证系统复杂度不高:采用服务调用者自身颁发序列号,同时生成方式采用时间戳的方式。服务端校验流程如下:
其中服务有效期可以自己选择定义(可以是半小时,一小时等等),选择的参考就是首先客户端这边与服务端最大可容忍的时间差是多大,其次就是自己的存储预估,如果存储越大,那么可以放的更宽一些。这种设计在容忍值内采用的是不重复性的校验,毕竟时间戳方式也是不重复的,这样减少了在短时间内由于并发和并行带来的顺序控制难的问题,其次在容忍值后采用的是递增校验,这样可以减少对于序列号的存储压力,可根据自身存储能力考虑最大的容忍时间。
欢迎讨论...