springboot框架实现锁住连续登录失败的用户

在springboot框架下锁住连续登录失败的用户

具体场景和操作是自行实现,基础代码参考自: SpringBoot注册登录(四):登录功能–密码错误三次,需要等待2分钟才能登录,固定时间内不能登录.

介绍

第一次写博客,想分享下学到的知识和自己的想法,希望能够帮助同样受到困惑的朋友,同时也是给容易失忆的自己留个mark,由于我容易忘所以我喜欢把这些东西写得稍微详细点.如果有什么错误希望大家帮忙指出,本人语言组织有点差,希望多多谅解.这个知识也是我站在巨人的肩膀上前进,所以非常感谢帮助我的博主.

问题

在springboot框架下的登录界面,如何实现把重复登录失败的用户进行锁定,防止有人通过无限试错来刷出密码.

对问题的想法

首先,我想到的是对数据库的表增加字段,用于查询判断这个用户的情况,根据返回的结果做出不同的判断,是锁住用户还是常规用户.

具体操作

1.首先,根据需求,我想对用户表(假定是user表)进行新添加字段:第一个是登录失败次数(为int类型默认为0,不准为空).第二个是允许登录的时间(datetime类型,允许为空)[这个两个字段就足够对这个问题解决,但后来我发现会存在一个小问题,按照之后的逻辑会对三次登录失败的用户锁三分钟,假设我有个用户,先猴急登录了2次,全都失败了,有点慌,怕被锁住,思考了三分钟,想出个几个密码,先去试了下第一个,还是出错了,那就会进入到三分钟锁定阶段.这个用户不服,我都思考了三分钟,你还要我等三分钟.如果考虑这种情况,我们想人性化点三分钟后清除,可以再加个字段上次测试的时间,但我当时处理的时候没考虑,就算了]

// 数据库里面负责添加字段的代码
ALTER table user
ADD times int NOT NULL DEFAULT 0 ;
ALTER table user
ADD allow_time DATETiME ;

2.在对应的项目文件domain的User项目中把新加入的字段和方法写入(User类里面写表相应的字段和方法,就是持久层的处理,假设我其他的字段都已经写好了,方式为通过注解进行处理)

// 持久层的数据
private Long times;
    private Date allow_time;

    @Column(name = "times")//这里对应的是数据库字段名

    public Long getTimes() {
        return times;
    }

    public void setTimes(Long times) {
        this.times = times;
    }


    @Colume(name = "allow_time")

    public Date getAllow_time() {
        return allow_time;
    }

    public void setAllow_time(Date allow_time) {
        this.allow_time = allow_time;
    }

3.接下来操作对应的Controller项目,假设我已经有一个login的方法了,他在UserController类,url是 巴拉巴拉+/login.他已经实现了登录的其他操作.此时的修改思路为,在判断为密码失败的后面假如操作(失败了肯定是次数加一啊,如果用户名不存在或者出现其他的异常我们就不管了,毕竟你用户名都没有,怎么可能给你试出来,但如果一定要加也是可以的)此处,添加一个我们的方法lockedJudge,用于判断是否被锁住了.如果返回false代表被锁住了,返回true代表没被锁住,需要获取的参数是id(假设有个用于辨识用户的字段叫id)失败次数和允许时间(这两个参数是得到的参数,如果次数大于3后修改的数据会不一样,可能会埋下小伏笔),以及判断是否登录成功(如果被锁住的状态下让他测试出正确密码,可不能让他进去,否则我们一切都白费了,这个方法之后成功的部分也要有),就是我们增加的字段.操作为:

如果允许时间为空或者当前时间大于允许时间{
是:查询是否失败次数在三次以上[
是:三次以上的错误,把次数变成0,允许时间推迟到3分后,并返回false.代表锁住了.
不是:根据传入的第三个参数是否登录成功进行判断,密码错误进来说明现在没在锁住的阶段,但你密码错了,总要给我次数加一吧.成功进来就啥也不做,他们都是返回true.因为我们给的结果是账户是不是被锁住了.并不是密码是否正确(这里当初我自己把自己给绕了)
]
不是:说明没到解锁的时间,直接返回false代表锁住了
}

//我的判断是否锁住的代码
private boolean lockedJudge(int id, Long times, Date allow_time, boolean loginSuccess) {
        Date dateNow = new Date();
        if (allow_time == null || dateNow.getTime() > allow_time.getTime()) {
            if (times >= 3) {
                //等会要在Service层加把次数清零和时间推后三分钟的方法
                userService.TimeClear(id);
                Date dateAfterAllowTime = new Date(dateNow.getTime() + 18000);
                userService.pushAllowedTime(id, dateAfterAllowTime);
                System.out.println("三次密码错误,三分钟后再尝试");//假装是个报错信息
                return false;
            } else {
                if (loginSuccess) {
                    //登录成功了,次数是要变回0;
                    userService.TimeClear(id);
                    System.out.println("登录成功");
                    return true;
                } else {
                    //写个错误次数加一的方法
                    userService.allowedTimeAdd(id);
                    System.out.println("密码错误");
                    return true;
                }
            }
        } else {
            System.out.println("未到解锁时间");
            return false;
        }
    }

之后在成功的部分也加上这个方法,毕竟账户被锁住的优先级比较高嘛.接下来就讲下Service那边就把上面这三个方法写个接口,再到Impl里写给Rep类(假设我有个userRep已经写好了)加三个方法(如果出现报错说只有读取权限,没有修改权限之类的,就在方法前面加注解@Transactional(readOnly=false)),他的作用就是可以直接通过sql语句操作数据库,

    @Modifying
    @Query(value = "update User set  times=0 where id=?1 ")
    void TimeClear(int id);

    @Modifying
    @Query(value = "update User set  allow_time=?2 where id=?1 ")
    void pushAllowedTime(int id, Date dateAfterAllowTime);

    @Modifying
    @Query(value = "update User set  times=times+1 where id=?1 ")
    void pushAllowedTime(int id);

当然还可以再人性化点,可以再写个显示还有多少秒后账户解锁的方法,代码是写在成功和失败方法里面判断是否锁住的后面,此时就要根据我们方法的结果进行判断,被锁住了就再获取下当前的时间和修改后的允许登录时间(对上上面的小伏笔,注意这里要重新获取,否则只会取到没修改之前的数据),然后进行显示

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值