SpringBoot+Redis+SpringSecurity+mybatisplus+vue3使用redis的自动过期机制实现登录3次错误30秒后重置登录次数功能

紧接着上一篇的文章继续续写:

        当第三次错误后等待30秒,则我们需要将登录次数userLoginAttempts重置为0才能继续登录。最初代码是在等待完30秒后,进行一次判断,当超过30秒,我们将userLoginAttempts重置为0,如之前代码所示:

//如果登录次数超过3次时就会报出还需要等待多少秒
if(res.getUserLoginAttempts()>2){
	LocalDateTime lastLoginTime = res.getUserLoginLastTime();
	LocalDateTime currentTime = LocalDateTime.now();
	//判断
	Duration duration = Duration.between(lastLoginTime,currentTime);
	if (duration.getSeconds()<30){
		long i = 30;
		return Result.error("-1", "You still need to wait "+(i-duration.getSeconds())+"         seconds");
    }else {
        userService.updateLoginAttemptsZero(res.getUserId());
        return Result.error("-1","Login restrictions reset");
    }
}

        这样写的话就会在等待30秒重试后再次点击重置userLoginAttempts,这样就非常的不合理,就达不到所谓的登录错误3次等待30秒后再次登录这个需求。于是就思考了一个问题,如果在等待30秒错误的时候直接将userLoginAttempts重置为0,这样在提示框就不会出现Login restrictions reset。

        一、使用定时器来解决这个问题,在修改第三次错误登录时间这个接口的时候,通过异步@Async的方式使userLoginAttempts重置为0。

        二、使用的数据库为mysql,则使用mysql里的触发器来解决这个问题。

        三、使用redis的自动过期机制解决这个问题,当用户登录次数2的时候,将用户的邮箱号userEmail作为键,用户的userIds作为值存储至redis中,再通过onMessage判断userEmail是否存在,如果不存在直接将userLoginAttempts重置为0,代码如下:

if(res.getUserLoginAttempts() == 2){
	res.setUserLoginLastTime(LocalDateTime.now());
	// 2.将我们的token存放到rdis中
	redisUtils.setString(res.getUserEmail(), res.getUserIds() + "", 30L);
	userService.updateuserLoginLastTime(res);
	return Result.error("-1","You will need to wait 30 seconds before logging in");
}

 redis监听器代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

重置userLoginAttempts代码如下:

import lombok.extern.slf4j.Slf4j;
import org.cqipc.edu.bean.User;
import org.cqipc.edu.mapper.UserMapper;
import org.cqipc.edu.service.UserService;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer){
        super(listenerContainer);
    }

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserService userService;
    /*
    使用该方法监听,当我们的key失效的时候执行该方法
     */
    @Override
    public void onMessage(Message message, byte[] pattern){
        String expirakey = message.toString();
//        log.info("该key :expiraKey:" + expirakey + "失效啦");
        log.error("该key :expiraKey:" + expirakey + "失效啦");
        User userEmail = userMapper.getUserEmail(expirakey);
        if (userEmail == null){
            return;
        }
        userService.updateLoginAttemptsZero(userEmail.getUserId());
    }
}

这样就能实现这个功能,完整代码地址:student-erp: student-erp后端基于Spring Boot框架,前端基于vue3框架,使用Sping Security作为安全框架,目前专注于对各个院校的管理,针对到学生/教师/管理员、班级、专业、学院、大学之间的权限管理问题。学生/教师/管理员直接通过用户表,角色表来区分三者之间的区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程汐笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值