Java请求中关于如何避免防重放攻击

重放攻击介绍

防止重放攻击的方法是使用不重数

  1. 加随机数
    该方法优点是认证双方不需要时间同步,双方记住使用过的随机数,如发现报文中有以前使用过的随机数,就认为是重放攻击。缺点是需要额外保存使用过的随机数,若记录的时间段较长,则保存和查询的开销较大。
  2. 加时间戳
    该方法优点是不用额外保存其他信息。缺点是认证双方需要准确的时间同步,同步越好,受攻击的可能性就越小。但当系统很庞大,跨越的区域较广时,要做到精确的时间同步并不是很容易。)

我的做法是:
方法: 时间戳校验 + mac签名校验 双重验证
具体是:
在项目里面,当客户端请求我服务器的时候,会给我传递一些公共参数,比如客户端请求的时间戳,以及加密后的mac签名。
第一步: 我在拦截器里面拿到请求时间戳之后,转换为毫秒值,这时候我服务器端也会生成一个当前时间毫秒值,做差值比较
if((当前时间-请求时间)>60000 );//60秒
那就认为请求报文已经被拦截,正在攻击,说明此请求异常,结束请求。
如果是<60000毫秒 ,暂时认为是符合的(有疑问往下看),让请求继续往下走。
3,使用请求序列号方式(可代替mac签名)
虽然使用时间戳方式可以在一定程度上控制重放攻击,但是存在时间限制。在指定时间窗口下,任然不可避免会受到攻击。
服务器端和客户端约定一个序列号生成算法(保证全局唯一性),客户端每次请求时都需要携带请求序列号。
服务器端接到请求时,先验证序列号是否合法,不合法直接拒绝。否则查看缓存中是否已经存在过该序列号,若已经存在,表明该请求已经被处理,不允许再次调用。
本次处理完毕,将请求序列号缓存。
这样可以保证一个序列号对应的请求只会被处理一次,相对比较安全地杜绝了重放攻击。
比较时间差值:

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

		long req_time = simpleDateFormat.parse("20190625093842").getTime();
		long now_time =  new Date().getTime();
		
		(now_time-req_time)>60000
 在步骤一的基础上, 已经判断了时间差值, 不安全,因为一秒钟就可能被请求很多次,所以还需要进行mac验证。
   这时候我借助了cache缓存器 (CacheManager类) , 思路是:
     把客户端请求mac签名作为key,客户端请求时间戳作为value,保存到cache里面,
     cache(mac, time, cache名字)  到cache里面。
     
      此时已经保存,然后下次客户客户端请求,先根据加密后的mac签名和缓存名去cache里面取值,如果能拿到请求时间key, 不为空,就可以断定正在被重放攻击(数据重复),需要拦截下来。如果根据时间戳拿不到mac,说明正常请求,然后把正常请求的mac,请求时间戳 保存到cache里面就行了。
      ![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/58538ec638945525726de8ab46b84c66.png)
      timeToLiveSeconds="60":  缓存里60秒后会失效,这样就不会一直累加到缓存里面(当然有redis也可以借助redis).  大概就是这么个步骤。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

       											do-time:2019/6/25  
       											笔者:dk
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值