Spring Boot如何利用拦截器加缓存完成接口防刷操作

目录
  • 为什么需要接口防刷
  • 技术解析
  • 主要代码
  • 测试结果
  • 总结

为什么需要接口防刷

为了减缓服务器压力,将服务器资源留待给有价值的请求,防止恶意访问,一般的程序都会有接口防刷设置,接下来介绍一种简单灵活的接口防刷操作

技术解析

主要采用的技术还是拦截+缓存,我们可以通过自定义注解,将需要防刷的接口给标记出来管理,利用缓存统计指定时间区间里,具体的某个ip访问某个接口的频率,如果超过某个阈值,就让他进一会儿小黑屋,到期自动解放

主要代码

前置环境搭建,Spring Boot项目,引入Web和Redis依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
	</dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
</dependencies>

自定义注解

定义拦截器,重写preHandler方法

@Override
	public boolean preHandle(HttpServletRequest request ,HttpServletResponse response ,Object handler) throws Exception {

        log.info("------------接口防刷拦截器---------------");

        if (handler instanceof HandlerMethod) {

            HandlerMethod handlerMethod = (HandlerMethod) handler;

            AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
            // 如果没有该注解,则不在防刷目标里,直接返回
            if (accessLimit == null) {
                return true;
            }
            // 获取最大访问次数
            int maxAccessCnt = accessLimit.maxAccessCnt();
            // 获取ip
            String key = getRealIp(request);
            // ip+请求的接口路径 => 唯一标识key
            key += request.getRequestURI();

            //当前访问次数
            Object value = redisTemplate.opsForValue().get(key);

            if (value == null) {
                //第一次访问 设置key保留时长为1s
                redisTemplate.opsForValue().set(key, 1, 1L, TimeUnit.SECONDS);
            } else {

                Integer currentCnt = (Integer) value;

                if (currentCnt < maxAccessCnt) {
                    //对应key值自增
                    redisTemplate.opsForValue().increment(key);
                } else {
                    //超出接口时间段内允许访问的次数,直接返回错误信息,同时设置过期时间 20s自动剔除
                    redisTemplate.expire(key, 20L,TimeUnit.SECONDS);
                    response.setContentType("application/json;charset=utf-8");
                    try {
                        OutputStream out = response.getOutputStream();
                        out.write("访问次数已达上线!请稍后再访问".getBytes(StandardCharsets.UTF_8));
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return false;
                }
            }

        }
        return true;
    }

添加到需要防刷的接口上

/**
 * 返回不携带data的(成功例子)
 * @return
 */
@AccessLimit
@GetMapping("/getPaperS")
public ApiResult getPaperInfoSuccess() {
   if (log.isInfoEnabled()) {
      log.info("收到获取paper信息请求...");
   }
   //...业务逻辑
   if (log.isInfoEnabled()) {
      log.info("完成获取paper信息请求,准备返回对象信息");
   }
   return ApiResultGenerator.success();
}

测试结果

正常情况下

到底时间段内最大访问次数时

总结

到此这篇关于Spring Boot如何利用拦截器加缓存完成接口防刷操作的文章就介绍到这了,更多相关Spring Boot接口防刷操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot项目中接口防刷的完整代码

    一.自定义注解 import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author Yang * @version 1.0 * @date 2021/2/22

  • 基于注解实现 SpringBoot 接口防刷的方法

    该示例项目通过自定义注解,实现接口访问次数控制,从而实现接口防刷功能,项目结构如下: 一.编写注解类 AccessLimit package cn.mygweb.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Targ

  • Spring Boot如何利用拦截器加缓存完成接口防刷操作

    目录 为什么需要接口防刷 技术解析 主要代码 测试结果 总结 为什么需要接口防刷 为了减缓服务器压力,将服务器资源留待给有价值的请求,防止恶意访问,一般的程序都会有接口防刷设置,接下来介绍一种简单灵活的接口防刷操作 技术解析 主要采用的技术还是拦截+缓存,我们可以通过自定义注解,将需要防刷的接口给标记出来管理,利用缓存统计指定时间区间里,具体的某个ip访问某个接口的频率,如果超过某个阈值,就让他进一会儿小黑屋,到期自动解放 主要代码 前置环境搭建,Spring Boot项目,引入Web和Redi

  • spring boot如何添加拦截器

    构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Application.class, useDefaultFilters = true) public class ServletContextConfig extends WebMvcConfigurationSupport { 为了方便扫描位置,我们可以写一个接口或者入口类Application放置于最外

  • spring boot中interceptor拦截器未生效的解决

    目录 interceptor拦截器未生效 开始用的spring boot版本为1.5.6 解决方案 HandlerInterceptor实现登录失效拦截等 首先写一个实现HandlerInterceptor的类 然后把这个拦截器注册到spring中 interceptor拦截器未生效 搭建项目时发现拦截器未生效 开始用的spring boot版本为1.5.6 代码如下: @Configuration public class WebConfig extends WebMvcConfigurerA

  • Spring boot如何基于拦截器实现访问权限限制

    遇到一个需求是:要为用户设置不同的菜单.数据访问权限.对于一些特定类型的数据,有的用户可以看有的用户则不可以.一开始没有太多思路,后来一想是不是可以把"特定类型"这个参数通过@PathVariable注解加到路径上,这样就可以通过拦截器拦截后,校验此用户是否可以访问这个路径(类型)下的数据了. 话不多说,以下为具体实践 拦截器配置类 @Configuration public class UserInterceptorConfig { //为了保证IDbnetUserService提前

  • 利用spring的拦截器自定义缓存的实现实例代码

    本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示. Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.本文利用Memcached 的实例和spring的拦截器实现缓存自定义的实现.利用拦截器读取自定义的缓存标签,key值的生成策略. 自定义的Cacheable package com.jeex.sci; @Target(ElementT

  • Spring Boot使用过滤器和拦截器分别实现REST接口简易安全认证示例代码详解

    本文通过一个简易安全认证示例的开发实践,理解过滤器和拦截器的工作原理. 很多文章都将过滤器(Filter).拦截器(Interceptor)和监听器(Listener)这三者和Spring关联起来讲解,并认为过滤器(Filter).拦截器(Interceptor)和监听器(Listener)是Spring提供的应用广泛的组件功能. 但是严格来说,过滤器和监听器属于Servlet范畴的API,和Spring没什么关系. 因为过滤器继承自javax.servlet.Filter接口,监听器继承自ja

  • Spring Boot命令行运行器的实现方法

    CommandLineRunner是一个带有run方法的简单spring引导接口.Spring Boot启动后将自动调用实现CommandLineRunner接口的所有bean的run方法. Command Line Runner在加载应用程序上下文之后以及Spring Application run方法完成之前执行,相当于你的应用的初始化过程,一般用来实现一些数据预先加载或预先处理. @SpringBootApplication <b>public</b> <b>cl

  • 在Spring Boot中从类路径加载文件的示例

    资源加载器 使用Java,您可以使用当前线程的classLoader并尝试加载文件,但是Spring Framework为您提供了更为优雅的解决方案,例如ResourceLoader. 您只需要自动连接ResourceLoader,然后调用getResource(„somePath")方法即可. 在Spring Boot(WAR)中从资源目录/类路径加载文件的示例 在以下示例中,我们从类路径中加载名为GeoLite2-Country.mmdb的文件作为资源,然后将其作为File对象检索. @Se

  • Springboot如何利用拦截器拦截请求信息收集到日志详解

    目录 1.需求 2.问题 2.获取 1)导入依赖为了获取客户端类型.操作系统类型.ip.port 2)封装获取body字符串的工具类 3)拦截器类 4)继承 HttpServletRequestWrapper类 5)过滤器类 6)拦截器过滤器配置类 总结 1.需求 最近在工作中遇到的一个需求,将请求中的客户端类型.操作系统类型.ip.port.请求方式.URI以及请求参数值收集到日志中,网上找资料说用拦截器拦截所有请求然后收集信息,于是就开始了操作: 2.问题 试了之后发现当请求方式为POST,

  • spring boot中的静态资源加载处理方式

    1.spring boot默认资源处理 Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性. spring boot默认加载文件的路径是: /META-INF/resources/ /resources/ /static/ /public/ 这些目录下面, 当然我们也可以从spring boot源码也可以看到Java代码: private static final String[] CLASSPATH_RESOURCE_L

随机推荐