在上一次写的文章中,为大家说到了如何动态的从数据库加载用户、角色、权限信息,从而实现登录验证及授权。在实际的开发过程中,我们通常会有这样的一个需求:当用户多次登录失败的时候,我们应该将账户锁定,等待一定的时间之后才能再次进行登录操作。
要实现多次登录失败账户锁定的功能,我们需要先回顾一下基础知识:
建议您先阅读本文,如果您对本文的实现过程感到迷惑,建议您再翻看本号之前的相关内容。
一般来说实现这个需求,我们需要针对每一个用户记录登录失败的次数nlock和锁定账户的到期时间releasetime。具体你是把这2个信息存储在mysql、还是文件中、还是redis中等等,完全取决于你对你所处的应用架构适用性的判断。具体的实现逻辑无非就是:
这是一种非常典型的实现方式,笔者向大家介绍一款非常有用的开源软件叫做:ratelimitj。这个软件的功能主要是为api访问进行限流,也就是说可以通过制定规则限制api接口的访问频率。那恰好登录验证接口也是api的一种啊,我们正好也需要限制它在一定的时间内的访问次数。
首先需要将ratelimitj通过maven坐标引入到我们的应用里面来。我们使用的是内存存储的版本,还有redis存储的版本,大家可以根据自己的应用情况选用。
<dependency> <groupid>es.moki.ratelimitj</groupid> <artifactid>ratelimitj-inmemory</artifactid> <version>0.4.1</version> </dependency>
之后通过继承simpleurlauthenticationfailurehandler ,实现onauthenticationfailure方法。该实现是针对登录失败的结果的处理,在我们之前的文章中已经讲过。
@component public class myauthenticationfailurehandler extends simpleurlauthenticationfailurehandler { @autowired userdetailsmanager userdetailsmanager; //规则定义:1小时之内5次机会,就触发限流行为 set<requestlimitrule> rules = collections.singleton(requestlimitrule.of(1 * 60, timeunit.minutes,5)); requestratelimiter limiter = new inmemoryslidingwindowrequestratelimiter(rules); @override public void onauthenticationfailure(httpservletrequest request, httpservletresponse response, authenticationexception exception) throws ioexception, servletexception { string userid = //从request或request.getsession中获取登录用户名 //计数器加1,并判断该用户是否已经到了触发了锁定规则 boolean reachlimit = limiter.overlimitwhenincremented(userid); if(reachlimit){ //如果触发了锁定规则,通过userdetails告知spring security锁定账户 user.setaccountnonlocked(false); userdetailsmanager.updateuser(user); sysuser user = (sysuser) userdetailsmanager.loaduserbyusername(userid); } //此处省略通过response做json或html响应 } }
user.setaccountnonlocked(true);
重置锁定状态很简单,就是上面的代码。但是更重要的是如何选择重置锁定状态的时机。笔者能想到几种方案如下
写一个spring 的定时器轮询,当然这是最差的方案。
本文转载注明出处(必须带连接,不能只转文字):。
如对本文有疑问, 点击进行留言回复!!
荐 So easy!Nginx+SpringBoot 实现负载均衡
Java——三大分支:JavaSE、JavaEE、JavaME(概念理解)
荐 Spring Cloud OAuth2实现手机验证码登录
网友评论