请求重放拦截器

概念

重放攻击(英语:replay attack,或称为回放攻击)是一种恶意或欺诈的重复或延迟有效数据的网络攻击形式。 这可以由发起者或由拦截数据并重新传输数据的对手来执行,这可能是通过IP数据包替换进行的欺骗攻击的一部分。 这是“中间人攻击”的一个较低级别版本。
这种攻击的另一种描述是: “从不同上下文将消息重播到安全协议的预期(或原始和预期)上下文,从而欺骗其他参与者,致使他们误以为已经成功完成了协议运行。”

说白了,中间人拿着你的请求数据多次请求,多次请求中数据都是一样的

解决方案

加时间戳,在请求头或者是请求体中加。然后在全局统一的过滤器或者是拦截器对请求地址,参数,时间戳进行拼接,拼接之后使用MD5哈希过后以此作为Key判断Redis中是否存在相同的Key,如果存在则认定为是重放攻击,拦截不让放行,否则的话就不是,此时需要存入Redis中,并且设置过期时间。过期时间不宜过长,具体失效时间看个人

代码实现
/**
 * @Author: 资深高级Java开发工程师
 * @CreateDate: 2023/8/6
 * @Description: 请求重放过滤器
 */
@Order(1)
@WebFilter(urlPatterns = "/*", filterName = "PlaybackFilter", asyncSupported = true)
@Component
public class PlaybackFilter implements Filter {
    private static final String TIME_STAMP = "timeStamp";
    private static final int DEFAULT_EXPIRE_TIME = 30;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private RedisPrefix redisPrefix;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest r = (HttpServletRequest) request;
        String header = r.getHeader(TIME_STAMP);
        String requestUrl = r.getRequestURI();
        String requestBody = IOUtils.toString(request.getReader());
        MD5 md5 = MD5.create();
        String summary = requestUrl + requestBody + header;
        String key = md5.digestHex(summary);
        String redisKey = redisPrefix.getPlaybackKey() + key;
        Boolean hasKey = redisTemplate.hasKey(redisKey);
        //如果存在Key则不放行,return
        if (Boolean.TRUE.equals(hasKey)) {
            return;
        }
        execLua(redisKey);
        chain.doFilter(request, response);
    }

    /**
     * 使用Lua脚本执行原子性的Redis操作,
     * 如果key不存在则设置value为1并且设置过期时间为30秒,
     */
    private void execLua(String key) {
        RedisScript<Long> script = new DefaultRedisScript<>("if redis.call('exists', KEYS[1]) == 0 then\n" +
                "  redis.call('set', KEYS[1], 1, 'ex', " + DEFAULT_EXPIRE_TIME + ")\n" +
                "  return 1\n", Long.class);
        redisTemplate.execute(script, Collections.singletonList(key));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值