mysql 用户 多次登录失败_Spring Security之多次登录失败后账户锁定功能的实现

在上一次写的文章中,为大家说到了如何动态的从数据库加载用户、角色、权限信息,从而实现登录验证及授权。在实际的开发过程中,我们通常会有这样的一个需求:当用户多次登录失败的时候,我们应该将账户锁定,等待一定的时间之后才能再次进行登录操作。

一、基础知识回顾

要实现多次登录失败账户锁定的功能,我们需要先回顾一下基础知识:Spring Security 不需要我们自己实现登录验证逻辑,而是将用户、角色、权限信息以实现UserDetails和UserDetailsService接口的方式告知Spring Security。具体的登录验证逻辑Spring Security 会帮助我们实现。

UserDetails接口中有一个方法叫做isAccountNonLocked()用于判断账号是否被锁定,也就是说我们应该通过该方法对应的set方法setAccountNonLocked(false)告知Spring Security该登录账户被锁定。

那么应该在哪里判断账号登录失败的次数并执行锁定机制呢?当然是我们之前文章给大家介绍的《自定义登录成功及失败结果处理》的AuthenticationFailureHandler。

建议您先阅读本文,如果您对本文的实现过程感到迷惑,建议您再翻看本号之前的相关内容。

二、实现多次登录失败锁定的原理

一般来说实现这个需求,我们需要针对每一个用户记录登录失败的次数nLock和锁定账户的到期时间releaseTime。具体你是把这2个信息存储在mysql、还是文件中、还是redis中等等,完全取决于你对你所处的应用架构适用性的判断。具体的实现逻辑无非就是:登陆失败之后,从存储中将nLock取出来加1。

如果nLock大于登陆失败阈值(比如3次),则将nLock=0,然后设置releaseTime为当前时间加上锁定周期。通过setAccountNonLocked(false)告知Spring Security该登录账户被锁定。

如果nLock小于等于1,则将nLock再次存起来。

在一个合适的时机,将锁定状态重置为setAccountNonLocked(true)。

这是一种非常典型的实现方式,笔者向大家介绍一款非常有用的开源软件叫做:ratelimitj。这个软件的功能主要是为API访问进行限流,也就是说可以通过制定规则限制API接口的访问频率。那恰好登录验证接口也是API的一种啊,我们正好也需要限制它在一定的时间内的访问次数。

三、具体实现

首先需要将ratelimitj通过maven坐标引入到我们的应用里面来。我们使用的是内存存储的版本,还有redis存储的版本,大家可以根据自己的应用情况选用。

es.moki.ratelimitj

ratelimitj-inmemory

0.4.1

之后通过继承SimpleUrlAuthenticationFailureHandler ,实现onAuthenticationFailure方法。该实现是针对登录失败的结果的处理,在我们之前的文章中已经讲过。

@Component

public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

@Autowired

UserDetailsManager userDetailsManager;

//规则定义:1小时之内5次机会,就触发限流行为

Set 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响应

}

}核心实现注意看代码中的注释

代码中的SysUser为UserDetails的实现类,如果不知道如何实现请参考本号之前的文章

userDetailsManager被用于管理UserDetails信息,通过改变UserDetails改变Spring Security验证行为。

四、重置锁定状态的时机

user.setAccountNonLocked(true);

重置锁定状态很简单,就是上面的代码。但是更重要的是如何选择重置锁定状态的时机。笔者能想到几种方案如下下一次登陆的时候,自定义过滤器,加在Spring Boot过滤器链最前端做锁定状态重置的判断。

当登录账户被锁定之后,之后用户的每一次登录都会抛出LockedException。我们完全可以通过Spring Boot的全局异常捕获机制,在其中捕获LockedException,并做锁定状态的判断及重置行为。

写一个Spring 的定时器轮询,当然这是最差的方案。

期待您的关注本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的问题。你想知道如何使用 PHP 实现用户注册和登录,但是不使用 MySQL 数据库。那么,我可以给你一些思路和建议,希望能帮助到你。 首先,你需要明确你要使用哪种数据存储方式来保存用户信息。如果不使用 MySQL,可以考虑使用其他的关系型数据库,比如 PostgreSQL、SQLite 等,或者使用非关系型数据库,比如 MongoDB、Redis 等。或者,你也可以考虑使用文件系统来存储用户信息,比如将用户信息保存在 JSON 格式的文件中。 其次,你需要设计用户表的结构,包括哪些字段需要保存,比如用户名、密码、邮箱、注册时间等。对于密码,你需要使用加密算法来保证数据安全,比如使用 PHP 的 password_hash() 函数进行加密,使用 password_verify() 函数进行验证。 接下来,你可以编写 PHP 代码来实现用户注册和登录功能。对于注册功能,你需要编写一个表单页面,用户可以在页面上输入自己的信息,然后将信息提交到 PHP 文件中进行处理。在 PHP 文件中,你需要将用户输入的信息进行验证和处理,然后将用户信息保存到数据库或文件中。 对于登录功能,你也需要编写一个表单页面,用户可以在页面上输入自己的用户名和密码,然后将信息提交到 PHP 文件中进行验证。在 PHP 文件中,你需要查询数据库或文件,比对用户输入的用户名和密码是否与保存的信息一致,然后根据验证结果进行相应的处理,比如跳转到登录成功页面或提示用户登录失败。 最后,你需要注意安全问题,比如防止 SQL 注入、XSS 攻击等,确保用户信息的安全性和可靠性。 希望这些思路和建议能对你有帮助。如果你有其他问题或疑问,可以继续向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值