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

news/2024/12/21 10:00:36/

目录

  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作为存储介质:

java">@Component
public class AntiReplayInterceptor extends HandlerInterceptorAdapter {private static final String REQUEST_ID = "requestId";private static final long EXPIRE_TIME_IN_SECONDS = 60 * 5;@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Overridepublic 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();// 检查是否已经处理过该请求IDif (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配置中,以确保它能够应用于指定的请求路径:

java">@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate AntiReplayInterceptor antiReplayInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(antiReplayInterceptor).addPathPatterns("/inner/public/syncOrder/v1");}
}

路径模式匹配

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

适配器模式的魅力

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

总结

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


http://www.ppmy.cn/news/1556898.html

相关文章

Node.js安装(含npm安装vue-cli,安装element-ui)的详细配置

搭建前端框架 前端平台 量子计算机–10^5级别运算只需5min&#xff0c;这代表可以计算从宇宙大爆炸到现在的数据可以计算 安卓工程师–.xml node.js 下载 运行在win/linus的js——node.js 安装 建议不要动路径&#xff0c;可以避免很多问题&#xff0c;但是要保证C盘有至少1…

程序算术题-5

程序算术题-5 求这一天是在这一年的多少天题目逻辑方法一方法二 实例代码 求这一天是在这一年的多少天 题目 输入某年某月某日&#xff0c;判断这一天是这一年的第几天&#xff1f; 逻辑 /*** 求这一天是这一年的多少天* args[0] 年* args[1] 月* args[2] 日*/第一个输入参数…

点亮技术写作之路:CSDN文章创作秘籍分享

一、引言 &#xff08;一&#xff09;技术文章的重要性 在当今技术飞速发展的时代&#xff0c;优秀的技术文章扮演着举足轻重的角色&#xff0c;其重要性体现在多个关键方面。 首先&#xff0c;它是知识传承的核心载体。技术领域的知识如同浩瀚星辰&#xff0c;新的理念、方法…

在Linux系统中, 查询mysql

在Linux系统中&#xff0c;MySQL的启动文件通常位于/etc/init.d目录下&#xff0c;文件名通常以mysql或者mysqld开头。你可以使用以下命令来查找MySQL的启动脚本&#xff1a; sudo find / -name "mysql*" -type f 这个命令会搜索整个文件系统来找到所有以mysql开头…

【Java基础面试题025】什么是Java的Integer缓存池?

回答重点 Java的Integer缓存池&#xff08;Integer Cache&#xff09;是为了提升性能和节省内存。根据实践发现大部分的数据操作都集中在值比较小的范围&#xff0c;因此缓存这些对象可以减少内存分配和垃圾回收的负担&#xff0c;提升性能 在 -128到127范围内的Integer对象会…

如何利用大模型将语音转文字

如何利用大模型将语音转文字 OpenAI支持将语音转文字&#xff0c;调用接口可以直接将语音文件转为文字。 这个例子是调用了一个私有部署的Belle-whisper-large-v2-zh&#xff0c;使用OpenAI的客户端。 测试代码如下&#xff1a; from openai import OpenAIclient OpenAI(ba…

OpenEuler 22.03 安装 flink-1.17.2 集群

零&#xff1a;规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器&#xff0c;用于搭建 flink 集群。这里使用flink1.17.2 的原因&#xff0c;是便于后续与springboot的整合 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.…

Mybatis分页插件的使用问题记录

项目中配置的分页插件依赖为 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.7</version></dependency>之前的项目代码编写分页的方式为&#xff0c;通过传入的条件…