当前位置: 首页 > article >正文

拦截器魔法:Spring MVC中的防重放守护者

目录

  1. 简介
  2. HandlerInterceptorAdapter vs HandlerInterceptor
  3. 创建一个防重放拦截器
  4. 注册拦截器
  5. 路径模式匹配
  6. 适配器模式的魅力
  7. 总结

简介

在构建安全可靠的Web应用程序时,防止请求重放攻击是一项关键任务。当用户或系统发出的请求被恶意第三方捕获并重复发送给服务器时,就会发生重放攻击。这可能导致不必要的操作被执行,如重复下单、重复支付等。为了保护我们的应用免受此类威胁,我们可以利用Spring MVC框架提供的强大工具——HandlerInterceptor来实现防重放机制。

HandlerInterceptorAdapter vs HandlerInterceptor

当你决定为自己的应用添加自定义拦截逻辑时,可能会面临选择:是继承 HandlerInterceptorAdapter 还是直接实现 HandlerInterceptor 接口?两者之间的差异在于设计哲学和代码的简洁性。

  • HandlerInterceptorAdapter 是一个适配器类,它实现了 HandlerInterceptor 接口,并提供了所有方法的空实现。因此,如果你只需要覆盖部分方法,使用这个适配器可以让你的代码更加简洁。
  • HandlerInterceptor 接口则要求你必须显式地实现接口中定义的所有方法。这种方式虽然可能引入一些冗余代码,但它提供了更高的透明度,因为你清楚地知道有哪些方法需要处理。
  • 总结:extends HandlerInterceptorAdapter 只重写需要的方法即可,implements HandlerInterceptor需要重写所有方法,可能增加代码冗余

创建一个防重放拦截器

为了确保相同的请求不会被多次处理,我们需要在每次接收到POST请求时检查其唯一标识符(例如订单号或时间戳),并与服务器端存储的历史记录进行比较。下面是一个简单的防重放拦截器实现示例,这里我们使用Redis作为存储介质:

@Component
public class AntiReplayInterceptor extends HandlerInterceptorAdapter {

    private static final String REQUEST_ID = "requestId";
    private static final long EXPIRE_TIME_IN_SECONDS = 60 * 5;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if ("POST".equals(request.getMethod()) && 
            request.getRequestURI().startsWith("/inner/public/syncOrder/v1")) {
            
            // 获取请求体中的唯一标识符
            SynYxcRequest orderSyncDto = extractRequestBody(request);
            String requestId = orderSyncDto.getRequestId();
            
            // 检查是否已经处理过该请求ID
            if (redisTemplate.opsForValue().get(requestId) != null) {
                response.setStatus(HttpServletResponse.SC_CONFLICT);
                return false;
            } else {
                // 将请求ID存入Redis,并设置过期时间
                redisTemplate.opsForValue().set(requestId, "processed", EXPIRE_TIME_IN_SECONDS, TimeUnit.SECONDS);
            }
        }

        return true;
    }

    private SynYxcRequest extractRequestBody(HttpServletRequest request) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(request.getReader().lines().collect(Collectors.joining(System.lineSeparator())), SynYxcRequest.class);
    }
}

注册拦截器

有了拦截器之后,我们需要将其注册到Spring MVC配置中,以确保它能够应用于指定的请求路径:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AntiReplayInterceptor antiReplayInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(antiReplayInterceptor)
                .addPathPatterns("/inner/public/syncOrder/v1");
    }
}

路径模式匹配

如果不指定 .addPathPatterns() 方法,那么拦截器将会默认应用到所有路径。为了避免不必要的性能开销以及潜在的问题,你应该总是明确地定义你要拦截的路径模式。此外,你还可以使用 .excludePathPatterns() 来排除不需要拦截的路径。

适配器模式的魅力

通过使用 HandlerInterceptorAdapter,你可以轻松地只覆盖那些对你重要的方法,而无需关心其他方法。这种设计不仅简化了代码,也提高了可维护性。当然,如果你更喜欢一切都在掌控之中,直接实现 HandlerInterceptor 接口也是一个不错的选择。

总结

通过本文介绍的内容,我们了解了如何利用Spring MVC中的 HandlerInterceptorHandlerInterceptorAdapter 来构建一个高效的防重放拦截器。无论你是追求代码简洁还是完全控制,Spring都提供了灵活的解决方案,帮助你在Web开发的世界里游刃有余。希望这些知识能为你的项目增添一份安全保障,让每一次请求都能得到恰当的处理。


http://www.kler.cn/a/450047.html

相关文章:

  • 编译原理复习---正则表达式+有穷自动机
  • 21.打印文件地址 C#例子
  • 【Mysql】truncate 和 delete的区别
  • Flutter动画学习二
  • 智能座舱进阶-应用框架层-Jetpack主要组件
  • 安宝特应用 | 美国OSHA扩展Vuzix AR眼镜应用,强化劳动安全与效率
  • VSCode 插件开发实战(五):实现新语言支持和语法高亮
  • JavaEE进阶--mybatis使用测试日志参数传递浏览器访问
  • WPF 最小化到系统托盘
  • Vue3入门(7)
  • SQL语句整理五-StarRocks
  • 后端项目java中字符串、集合、日期时间常用方法
  • Strip Map和Wafer Map的一些小科普
  • Android修行手册 - 移动端几种常用动画方案对比
  • LLMs之PDF:MinerU(将PDF文件转换成Markdown和JSON格式)的简介、安装和使用方法、案例应用之详细攻略
  • Mac iOS、Android、Flutter、React Native开发环境配置
  • 【专题】2024抖音电商母婴行业分析报告汇总PDF洞察(附原数据表)
  • 【ArcGIS Pro】实现一下完美的坐标点标注
  • “年轻科技旗舰”爱玛A7 Plus正式发布,全国售价4999元
  • 【人工智能】探索当下热门视频生成模型
  • Elasticsearch:确保业务规则与语义搜索无缝协作
  • 项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(二)
  • MySQL数据库——复制表数据与结构
  • Zookeeper基本命令解析
  • 设计模式-访问者设计模式
  • linux Sudo权限