SpringBoot实现图形验证码功能+访问频率设置+缓存

这篇具有很好参考价值的文章主要介绍了SpringBoot实现图形验证码功能+访问频率设置+缓存。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、springboot实现图形验证码生成

1.1、导入Maven依赖

1.2、写一个生成图片的工具类

1.3、编写接口生成验证码并存入Redis

2、实现图形验证码判断是否正确

2.1、编写验证图形验证码接口

2.2、前端代码

2.3、请求发送

3、实现访问频率限制

3.1、创建自定义注解

3.2、创建自定义aop切面类


 文章来源地址https://www.toymoban.com/news/detail-854492.html

背景:我们在做项目登录功能的时候,为了防止被恶意攻击,发送大量请求,我们通常有一些需要人工进行验证

例如:短信验证登录,以及图形验证码登录这两者加上访问频率限制,用这种方式做到防止大量请求进来,对后端造成拥堵以及阻塞

接下来上图演示一下这种没有验证的功能和加上了验证的功能

这是没有加上验证功能,如果是这样子的话,很容易被人发送大量请求,导致服务器瘫痪

SpringBoot实现图形验证码功能+访问频率设置+缓存,缓存,spring boot,redis,后端,java

接下来我们来看看这个加上验证以及频率访问看看有什么效果吧

SpringBoot实现图形验证码功能+访问频率设置+缓存,缓存,spring boot,redis,后端,java

我们发现可以通过访问频率以及加上图形验证码来做防止大量请求进入和攻击

接下来上教程

1、springboot实现图形验证码生成

1.1、导入Maven依赖

我们可以使用这个hutool工具类来提供图形验证码的生成

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.6</version>
        </dependency>

1.2、写一个生成图片的工具类

在这里的工具类,我们有一个图片的唯一IDkey验证码以及图片的Base64值

我们将这三个数据以数组字符串的方式返回出去

package com.sxy.recordnetwork.common;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.util.Base64;

/**
 * 图形验证码生成工具类
 *
 * @author Administrator
 */
@Slf4j
public class ImgCodeUtil {
    /**
     * 画一个图片得到图片的唯一ID,和验证码,并且得到图片的base64
     *
     * @return
     */
    public String[] getImgIdCodeBase64() {
        try {
            // 生成一个宽度为80,高度为30的验证码图片
            LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(80, 30);
            // 生成唯一的验证码ID
            String captchaId = RandomUtil.randomString(6);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(lineCaptcha.getImage(), "png", baos);
            // 变为base64返回出去
            String base64 = Base64.getEncoder().encodeToString(baos.toByteArray());
            return new String[]{captchaId, lineCaptcha.getCode(), base64};
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

}

1.3、编写接口生成验证码并存入Redis

下面这段代码中两个方法:

        一个生成图形验证码,

        一个验证图形验证码。

还有两段重要的代码,RedisTemplate和IMG_KEY:存储唯一key

这两个方法我们先看第一个 生成图形验证码,

请求为Get请求,请求参数是路径参数,并且标注了一个自定义注解,这个注解后面会说到

另外一个方法后面再看

key:图形验证码的唯一key

email:前端传递过来的email邮箱

参数待会儿说,先说具体实现

通过redis创建一个操作普通字符串的方法

然后判断前端传过来的唯一key去查询是否存在该key如果存在则删除

接着,通过调用创建的图片生成工具类得到String类型的数组,数组内容长度为3,分别是,key,code,以及图片转base64

然后将key和code存入到Redis中形成键值对

至于base64,我们只需要将,key和base64构造成一个json对象,返回给前端即可展示即可

 

下面说一下这两个参数的作用:key和email

也就是说这两个参数必须得通过前端传递过来的。

为了防止第一次进入这个方法体,绕过上面的if判断,因为一开始是没有验证码的,直接删除可能会导致程序报错。所以这里的判断是这个key必须是前端传过来的值,并且根据这个key查找redis中是否存在这条数据,如果存在,则就删除。

所以我们在前端第一次传过来一个随机的数字,因为是第一次,所以第一次并不会进入这个if,所以就很显然进入了下面的代码,下面的代码通过创建图片,返回数据就可以了。

而当我们第二次,进入这个方法的时候,由于第一次创建的图片生成的Key返回给了前端,所以前端会携带这个key来到这个方法,这个时候key不为空并且redis数据库中根据这个key找到了这个数据,也就证明这是第二次重新获取图片验证码,这个时候,程序就会根据用户传递过来的key将原有的数据删除,然后再重新生成新的验证码并且返回给前端。这样以此类推,第三次、第四次、第五次等,都会按照这个流程来走。

email的作用到下面的访问频率再细说

package com.sxy.recordnetwork.controller.pcUser;


// import ...

import java.util.concurrent.TimeUnit;

/**
 * 第三方短信验证以及其他相关操作
 */
@RequestMapping("/pcClientUser/code")
@RestController
@Slf4j
public class CodeController {

    @Autowired
    private RedisTemplate redisTemplate;
    // ImgCodeKey
    private static String  IMG_KEY = "";

    /**
     * 生成图形验证码存入redis
     * @param key
     * @return
     */
    @AccessLimit
    @GetMapping("/getImgBase64/{key}/{email}")
    public Result getImgBase64(@PathVariable String key,@PathVariable String email) {
        //TODO 当我前端连续发送多次请求时,会有一部分key拿不到,就无法删除上一个
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 重复发送验证码,如果key存在则删除,否则就成为第一次继续生成
        if(key != null && redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }

        ImgCodeUtil imgCodeUtil = new ImgCodeUtil();
        String[] date = imgCodeUtil.getImgIdCodeBase64();
        // 将验证码存入到Redis中
        valueOperations.set(date[0], date[1]);
        // 构造json字符串,将唯一标识和base64数据存入返回给前端
        JSONObject entries = new JSONObject();
        entries.set("base64Image", "data:image/png;base64," + date[2]);
        entries.set("captchaKey", date[0]);
        // 返回给前端
        return Result.success("图形验证码获取成功", entries);
    }

    /**
     * 验证图形验证码,得到唯一标识和验证码
     * @param userDtoEmailLogin
     * @return
     */
    @PostMapping("/getEmailCode/")
    public Result getEmailCode(@RequestBody UserDtoEmailLogin userDtoEmailLogin) {
      // ......
    }
}

2、实现图形验证码判断是否正确

2.1、编写验证图形验证码接口

接下来我们看看第二个接口,

参数为一个DTO:我们创建一个DTO用于接收邮箱登录

参数列表中的emailCode先不管

package com.sxy.recordnetwork.DTO.USER;

import lombok.*;

/**
 * QQ邮箱验证登录的数据传输层
 */
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class UserDtoEmailLogin {
    private String email; //  email
    private String imgCode; //  图形验证码
    private String key; // 图形验证码的唯一key
    private String emailCode; // email验证码
}
package com.sxy.recordnetwork.controller.pcUser;


// import ...

import java.util.concurrent.TimeUnit;

/**
 * 第三方短信验证以及其他相关操作
 */
@RequestMapping("/pcClientUser/code")
@RestController
@Slf4j
public class CodeController {

    @Autowired
    private RedisTemplate redisTemplate;
    // ImgCodeKey
    private static String  IMG_KEY = "";

    /**
     * 生成图形验证码存入redis
     * @param key
     * @return
     */
    @AccessLimit
    @GetMapping("/getImgBase64/{key}/{email}")
    public Result getImgBase64(@PathVariable String key,@PathVariable String email) {
       // ......
    }

    /**
     * 验证图形验证码,得到唯一标识和验证码
     * @param userDtoEmailLogin
     * @return
     */
    @PostMapping("/getEmailCode/")
    public Result getEmailCode(@RequestBody UserDtoEmailLogin userDtoEmailLogin) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        System.out.println(userDtoEmailLogin);
        // 得到唯一标识key
        IMG_KEY = userDtoEmailLogin.getKey();
        // 通过key查找值看是否与传递过来的code相等,
        if (!userDtoEmailLogin.getImgCode().equals(valueOperations.get(IMG_KEY))) {
            // 不相等抛出异常
            throw new EmailCodeException(Constants.EMAIL_IMG_CODE_ERROR.getValue());
        }
        // 先不删除,等登陆成功后再删除相等就成功并将数据清空
//        redisTemplate.delete(key);
        // 返回成功
        return Result.success();
    }
}

我们来看看这个方法,这个方法的参数是一个DTO,上面演示了这个DTO中的内容

我们可以通过前端的参数,传入固定的email,前端传递过来的唯一标识key(固定传入),图形验证码  

然后创建一个操作普通字符串的方法

同门通过对象点出这个唯一的key存入本方法中的常量IMG_KEY,用来做持久化后续操作,只有在真正登陆后才会清除这个唯一key。

通过传递过来的key在Redis中查询出对应的value,判断是否与用户传递过来的code验证码匹配,不匹配则抛出异常。

注意:这个异常我用的全局异常处理器,并且声明了自定义异常类,在我往期的文章中讲到。

并且我们验证成功过后先不用删除,我们等后面真正登录成功之后再删除

注意:注意:注意:我这里只是演示了这两个方法,我并没有登陆方法,这个后续可以自己写,我就不写了

package com.sxy.recordnetwork.controller.pcUser;


// import ...

import java.util.concurrent.TimeUnit;

/**
 * 第三方短信验证以及其他相关操作
 */
@RequestMapping("/pcClientUser/code")
@RestController
@Slf4j
public class CodeController {

    @Autowired
    private RedisTemplate redisTemplate;
    // ImgCodeKey
    private static String  IMG_KEY = "";

    /**
     * 生成图形验证码存入redis
     * @param key
     * @return
     */
    @AccessLimit
    @GetMapping("/getImgBase64/{key}/{email}")
    public Result getImgBase64(@PathVariable String key,@PathVariable String email) {
       // ......
    }

    /**
     * 验证图形验证码,得到唯一标识和验证码
     * @param userDtoEmailLogin
     * @return
     */
    @PostMapping("/getEmailCode/")
    public Result getEmailCode(@RequestBody UserDtoEmailLogin userDtoEmailLogin) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        System.out.println(userDtoEmailLogin);
        // 得到唯一标识key
        IMG_KEY = userDtoEmailLogin.getKey();
        // 通过key查找值看是否与传递过来的code相等,
        if (!userDtoEmailLogin.getImgCode().equals(valueOperations.get(IMG_KEY))) {
            // 不相等抛出异常
            throw new EmailCodeException(Constants.EMAIL_IMG_CODE_ERROR.getValue());
        }
        // 先不删除,等登陆成功后再删除相等就成功并将数据清空
//        redisTemplate.delete(key);
        // 返回成功
        return Result.success();
    }
}

2.2、前端代码

api接口: 前端代码就不讲解了

import request from '@/utils/request.js'

// 得到图形验证码的base64状态
export const getCaptchaService = (key,email) => {
  return request.get('/code/getImgBase64/' + key + '/' + email)
}

// 验证图形验证码是否输入正确
export const checkCaptchaService = (data) => {
  return request.post('/code/getEmailCode/', data, {
    headers: {
      'Content-Type': 'application/json'
    }
  })
}

2.3、请求发送

<script setup>
import { ref, nextTick, onMounted } from 'vue'
import { loginBg, QQ, QQEmail, WB, WeChat } from '@/utils/ImageUtils.js'
import router from '@/router/index.js'
import { checkCaptchaService, getCaptchaService } from '@/api/login.js'
const loading = ref(false)
const loginShow = ref(true)
// 各种登录的信息
// 邮箱登录信息
const EmailLoginInfo = ref({
  email: '', // 邮箱
  imgCode: '', // 图片验证码
  key: '', // 图片验证码的唯一key
  emailCode: '' // 邮箱验证码
})
const MoreLogin = ref([
  {
    index: 0,
    loginName: 'email',
    detail: 'qq邮箱登录',
    icon: QQEmail
  }
])

// 页面元素加载完成后执行
onMounted(() => {
  changeCaptcha()
})
// 关联表单登录
const otherForm = ref()
// 得到图形验证码base64的数据加载图片
const captchaBase64 = ref()
// 绑定邮箱输入框
const EmailValidate = ref()
// 邮箱是否合法
const emailIsValid = ref(false)
// 切换图形验证码
const changeCaptcha = async () => {
  // 必须验证邮箱的格式是否正确以及不能为空才能发送
  await EmailValidate.value.validate()
  // 加载效果
  loading.value = true
  emailIsValid.value = true
  const { data } = await getCaptchaService(
    EmailLoginInfo.value.key ? EmailLoginInfo.value.key : '1',EmailLoginInfo.value.email
  )
  loading.value = false
  // 设置图片
  captchaBase64.value = data.base64Image
  // 设置图片的唯一标识key
  EmailLoginInfo.value.key = data.captchaKey
}
// 邮箱验证码的发送
const sendEmailCode = async () => {
  //TODO 验证图形验证码是否正确以及邮箱是否正确
  await checkCaptchaService(EmailLoginInfo.value)
  //TODO 发送邮箱验证码
}
// 邮箱登录
const emailLogin = async (index) => {
  // 点击登录先校验规则
  await otherForm.value.validate()
  console.log(index)
  //TODO 发送请求进行邮箱登录
}
// 表单验证规则
const rules = ref({
  // 邮箱账号验证规则
  email: ref([
    { required: true, message: '请输入您的邮箱', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
      message: '邮箱格式不正确',
      trigger: 'blur'
    }
  ]),
  // 验证码验证规则
  code: ref([{ required: true, message: '验证码不能为空', trigger: 'blur' }]),
  // 图形验证码的规则
  ImgCode: ref([{ required: true, message: '验证码不能为空', trigger: 'blur' }])
})
</script>

<template>
  <el-row>
    <el-col class="bg" :span="24" :style="{ background: 'url(' + loginBg + ') no-repeat' }">
      <el-row justify="center">
        <el-col class="MoreLogin" :offset="7" :span="9">
          <el-row>
            <el-col v-if="loginShow" class="returnLogin" :span="24" @mouseenter="loginShow = false">
              <span style="font-size: 16px">第三方登录</span>
            </el-col>
            <!-- 返回用户登录 -->
            <el-col
              v-else
              class="returnLogin"
              :span="24"
              @mouseleave="loginShow = true"
              @click="$router.replace('/record/login')"
            >
              <span style="font-size: 16px">返回用户登录</span>
            </el-col>
          </el-row>
          <!--          qq邮箱登录-->
          <el-row justify="center" v-if="activeLoginIndex === '0'">
            <el-col :span="18">
              <el-form
                label-width="110px"
                label-position="right"
                :rules="rules"
                ref="otherForm"
                status-icon
                :model="EmailLoginInfo"
              >
                <el-form-item label="QQ邮箱:" ref="EmailValidate" prop="email">
                  <el-input
                    v-model="EmailLoginInfo.email"
                    placeholder="请输入您的qq邮箱"
                  ></el-input>
                </el-form-item>
                <el-form-item label="图形验证码:" prop="ImgCode">
                  <el-input v-model="EmailLoginInfo.imgCode" placeholder="请输入图形验证码">
                    <template #append >
                      <div @click="changeCaptcha" v-loading='loading'>
                        <span v-if="emailIsValid">
                          <img
                            width="80"
                            height="30"
                            alt=""
                            v-if="captchaBase64"
                            :src="captchaBase64"
                          />
                        </span>
                        <span v-else>获取图形码</span>
                      </div>
                    </template>
                  </el-input>
                </el-form-item>
                <el-form-item label="邮箱验证码:" prop="code">
                  <el-input v-model="EmailLoginInfo.emailCode" placeholder="请输入您的六位验证码">
                    <template #append>
                      <span @click="sendEmailCode">发送验证码</span>
                    </template>
                  </el-input>
                </el-form-item>
                <el-form-item>
                  <el-button
                    style="width: 100%"
                    type="primary"
                    @click="emailLogin(activeLoginIndex)"
                    >登录
                  </el-button>
                </el-form-item>
              </el-form>
            </el-col>
          </el-row>
        </el-col>
      </el-row>
    </el-col>
  </el-row>
</template>

3、实现访问频率限制

3.1、创建自定义注解

这里有两个默认值,一个为允许访问的次数为5次,一个是在默认的60秒时间范围内访问的次数。也就是设置在Redis中数据的TTL(存活时间)

package com.sxy.recordnetwork.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 设置访问次数限制的注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
    int count() default 5; // 允许被访问的次数
    int seconds() default 60; // 时间范围,秒为单位,表示在60秒内访问的次数

}

3.2、创建自定义aop切面类

好,到了这里,我们上面第一个方法中的参数列表是如下以及注解

SpringBoot实现图形验证码功能+访问频率设置+缓存,缓存,spring boot,redis,后端,java

这个email有什么用呢,以及这个切面的自定义注解

我们先来说一下这个自定义切面的实现逻辑

给这个类标注上aop切面类和Component注解,交给spring管理

添加一个名为AccessLimitBefore这个方法

参数列表为:

        JoinPoint:用于获取指定方法上的参数

        AccessLimit:用于获取注解内的参数

在这个方法中添加了一个注解:@Before("@annotation(accessLimit)")

表示:添加一个前置通知(@Before)在方法执行之前执行,切入点是:满足了添加AccessLimit注解的方法进行拦截。

在方法内部创建了一个操作普通字符串的redis方法

获取一下自定义注解AccessLimit的属性 times(访问次数)、sencods(TTL过期时间)

使用参数列表中的第一个参数获取方法上的参数为一个Object类型,因为不知道是什么类型嘛,所以就设置为Object类型。

因为我们这里的方法参数列表有两个参数,一个key,一个email,这里的email就有用了 由于是两个参数,所以整体的参数列表就是0,1我们需要获取到email作为指定用户的key,防止多个用户同时操作且会覆盖,所以就需要用到email

然后我们判断是否为空,防止空指针报错

接着这里的key在参数列表中的第0个位置,而email在数组的1位置,所以判断必须要通过获取的列表的参数,拿到email,强制转换为Stiring

将key设置为:user_ + email

接着直接从Redis获取用户的访问次数

如果次数为空,则将次数设置为0

如果超出了访问次数times,则抛出异常,这里也是一样用到了常量类 + 全局异常处理器

注意:这个times表示的不是时间,而是默认的访问次数频率5,也就是自定义注解中的times属性

如果没有超出次数,则先获取上一次的TTL时间,重新设置一下时长,并且访问次数 + 1

package com.sxy.recordnetwork.aspect;

// ......

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 设置访问次数限制的AOP切面
 */
@Aspect
@Component
@Slf4j
public class AccessLimitAspect {

    @Autowired // redis
    private RedisTemplate redisTemplate;

    // 添加一个前置通知,在方法执行之前执行 切入点为满足添加了这个AccessLimit注解的方法
    @Before("@annotation(accessLimit)")
    public void AccessLimitBefore(JoinPoint joinPoint, AccessLimit accessLimit){
        // 设置一下redis的访问
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 获取注解属性
        int times = accessLimit.count(); //  访问次数
        int seconds = accessLimit.seconds(); // 在一定时间内
        // 获取方法上的参数
        Object[] args = joinPoint.getArgs();
        // 判断是否为空
        if (args == null || args.length == 0){
            return;
        }
        // 获取当前用户的邮箱号,来判断改用户是否已经访问过  参数为实体类的第二个参数
        String email = (String) args[1];
        // 设置key
        String key = "user_" + email;
        // 从Redis获取用户的访问次数
        Integer count = (Integer)valueOperations.get(key);
        System.out.println(count);
        if(count == null){
            count = 0;
        }
        // 如果超出了允许的访问次数,则抛出异常
        if(count >= times){
            throw  new EmailCodeException(Constants.FREQUENT_VISITS.getValue());
        }
        // 获取到redis中指定key的过期时间
        Long expire = redisTemplate.getExpire(key);
        // 判断TTL如果大于零表示存在,则设置过期时间为获取上一次的
        if(expire > 0){
            valueOperations.set(key,count + 1,expire,TimeUnit.SECONDS);
        }else{
            // 更新Redis中的计数器 单位为秒
            valueOperations.set(key,count + 1,seconds,TimeUnit.SECONDS);
        }

    }


}

总结:以上这种方式,可以方法攻击者,伪造大量请求进行攻击,导致服务器瘫痪。

使用了自定义注解和AOP切面,以及使用图形验证码生成的工具类,加上Redis做数据缓存,设置频率访问

 

到了这里,关于SpringBoot实现图形验证码功能+访问频率设置+缓存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot+Vue3实现登录验证码功能

    Redis缓存穿透、击穿、雪崩问题及解决方法 Spring Cache的使用–快速上手篇 分页查询–Java项目实战篇 全局异常处理–Java实战项目篇 Java实现发送邮件(定时自动发送邮件)_java邮件通知_心态还需努力呀的博客-CSDN博客 该系列文章持续更新,更多的文章请点击我的主页查看哦!

    2024年02月01日
    浏览(32)
  • 【项目功能模块】SpringBoot+vue实现登录图片验证码

    要在Spring Boot和Vue中实现登录时的图片验证码功能,可以按照以下步骤进行操作: 后端(Spring Boot)实现: 添加相关依赖:在 pom.xml文件中添加以下依赖: 创建一个验证码生成器:创建一个CaptchaGenerator类,用于生成验证码图片。 创建一个REST API接口:创建一个 CaptchaControlle

    2024年02月11日
    浏览(30)
  • 【项目功能模块拆分】SpringBoot+vue实现登录图片验证码

    要在Spring Boot和Vue中实现登录时的图片验证码功能,可以按照以下步骤进行操作: 后端(Spring Boot)实现: 添加相关依赖:在 pom.xml文件中添加以下依赖: 创建一个验证码生成器:创建一个CaptchaGenerator类,用于生成验证码图片。 创建一个REST API接口:创建一个 CaptchaControlle

    2024年02月11日
    浏览(28)
  • 【项目功能模块拆分】SpringBoot+vue实现登录手机验证码

    要在Spring Boot和Vue中实现登录需要手机验证码功能,你需要进行以下步骤: 后端(Spring Boot)实现: 添加相关依赖:在pom.xml文件中添加以下依赖: 创建一个验证码生成器:创建一个 CaptchaGenerator类,用于生成手机验证码。 创建一个REST API接口:创建一个 CaptchaController类,用于

    2024年02月11日
    浏览(28)
  • 前后端分离项目中实现业务中常用图形验证码验证功能(详细)

    图形验证码是验证码的一种,有防止黑客对某一特定注册用户用程序暴力破解私人信息、恶意破解密码、刷票、论坛灌水的作用。 图形验证码是一种区分用户是计算机还是人的公共全自动程序。验证码是现在很多网站通行的方式,由计算机生成并评判,但是只有人类才能解答

    2024年02月04日
    浏览(43)
  • SpringBoot限制接口访问频率 - 这些错误千万不能犯

    最近在基于SpringBoot做一个面向普通用户的系统,为了保证系统的稳定性,防止被恶意攻击,我想控制用户访问每个接口的频率。为了实现这个功能,可以设计一个annotation,然后借助AOP在调用方法之前检查当前ip的访问频率,如果超过设定频率,直接返回错误信息。 在开始介

    2024年02月05日
    浏览(34)
  • (短信服务)java SpringBoot 阿里云短信功能实现发送手机验证码

    阿里云官网: https://www.aliyun.com/ 点击官网首页注册按钮。 注册成功后,点击登录按钮进行登录。登录后进入短信服务管理页面,选择国内消息菜单: 短信签名是短信发送者的署名,表示发送方的身份。 切换到【模板管理】标签页: 短信模板包含短信发送内容、场景、变量信息

    2024年02月02日
    浏览(41)
  • 【前后端的那些事】SpringBoot 基于内存的ip访问频率限制切面(RateLimiter)

    限流就是在用户访问次数庞大时,对系统资源的一种保护手段。高峰期,用户可能对某个接口的访问频率急剧升高,后端接口通常需要进行DB操作,接口访问频率升高,DB的IO次数就显著增高,从而极大的影响整个系统的性能。如果不对用户访问频率进行限制,高频的访问容易

    2024年04月17日
    浏览(50)
  • openResty+lua+redis实现接口访问频率限制

    OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。 OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团

    2024年02月11日
    浏览(37)
  • springboot验证码生成及验证功能

    生成验证码的方式有许多种,这里选择的是easy-captcha工具包。 github开原地址为:easy-captcha工具包 其支持Java图形验证码,支持gif、中文、算术等类型,可用于Java Web、JavaSE等项目。 首先需要将easy-captcha的依赖配置文件增加到pom.xml文件中。 开源项目中已经写好了导入依赖语句

    2023年04月15日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包