基于Redis+lua 防止用户请求重复提交

Posted Dream_it_possible!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Redis+lua 防止用户请求重复提交相关的知识,希望对你有一定的参考价值。

需求

       一个用户3s内只能请求指定方法一次,例如发验证码场景。

依赖

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

lua 脚本

       用keys 来获取列表里的参数,下标从1开始, 用ARGV获取全局变量,下标从1 开始。

return redis.call('set', KEYS[1], 1, 'ex', ARGV[1], 'nx');

       此脚本的意思是:  通过setNx命令设置一个key=KEYS[1], value=1, 失效时间为 ARGV[1]

package com.example.prevent.controller;

import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;


/**
 * @decription:
 * @author: 
 * @date: 2021/6/2 19:54
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @PostMapping(value = "/submit")
    public boolean isReSubmit() {
        String key = "user_id";
        Integer expire = 3;
        ArrayList<String> keys = Lists.newArrayList(key);
        String result = stringRedisTemplate.execute(setNxWithExpireTime, keys, expire.toString());
        return !"ok".equalsIgnoreCase(result);
    }

    private RedisScript<String> setNxWithExpireTime = new DefaultRedisScript<>(
            "return redis.call('set', KEYS[1], 1, 'ex', ARGV[1], 'nx');",
            String.class
    );

}

 第一次请求:

 再次快速请求:

3s 的响应间隔时间内,是不允许再次重复提交!

以上是关于基于Redis+lua 防止用户请求重复提交的主要内容,如果未能解决你的问题,请参考以下文章

利用Redis实现防止接口重复提交功能

使用Redis实现接口防重复提交

使用Redis实现接口防重复提交

Redis使用系列使用Redis做防止重复提交

token防止前端重复提交

防重复提交实现方案