在上一次写的文章中,为你们说到了如何动态的从数据库加载用户、角色、权限信息,从而实现登陆验证及受权。在实际的开发过程当中,咱们一般会有这样的一个需求:当用户屡次登陆失败的时候,咱们应该将帐户锁定,等待必定的时间以后才能再次进行登陆操做。html
要实现屡次登陆失败帐户锁定的功能,咱们须要先回顾一下基础知识:前端
建议您先阅读本文,若是您对本文的实现过程感到迷惑,建议您再翻看本号以前的相关内容。mysql
通常来讲实现这个需求,咱们须要针对每个用户记录登陆失败的次数nLock和锁定帐户的到期时间releaseTime。具体你是把这2个信息存储在mysql、仍是文件中、仍是redis中等等,彻底取决于你对你所处的应用架构适用性的判断。具体的实现逻辑无非就是:redis
这是一种很是典型的实现方式,笔者向你们介绍一款很是有用的开源软件叫作:ratelimitj。这个软件的功能主要是为API访问进行限流,也就是说能够经过制定规则限制API接口的访问频率。那刚好登陆验证接口也是API的一种啊,咱们正好也须要限制它在必定的时间内的访问次数。spring
首先须要将ratelimitj经过maven坐标引入到咱们的应用里面来。咱们使用的是内存存储的版本,还有redis存储的版本,你们能够根据本身的应用状况选用。sql
<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);
重置锁定状态很简单,就是上面的代码。可是更重要的是如何选择重置锁定状态的时机。笔者能想到几种方案以下json