实现 Spring Cloud + Redis 密码输错5次锁定功能

在现代应用中,安全性是一个非常重要的方面,尤其是用户认证相关的功能。今天我们来实现一个基于 Spring Cloud 和 Redis 的用户密码错误五次锁定功能。这个功能可以有效防止暴力破解。

整体流程

下面是我们实现该功能的整体流程:

步骤 描述
1 用户输入密码
2 验证密码是否正确
3 如果正确则登录
4 如果错误,记录错误次数
5 当错误次数达到5次时锁定用户
6 锁定期间无法登录
7 用户输入正确密码后解锁

实现步骤

1. 添加依赖

pom.xml 中添加 Spring Boot 和 Redis 依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

这里我们引入了 Spring Boot 的 Redis 依赖和 Web 依赖。

2. 配置 Redis

application.propertiesapplication.yml 文件中配置 Redis 连接信息:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword # 根据需要修改密码

3. 创建用户服务

@Service
public class UserService {
    private static final String LOCKED_USER_PREFIX = "locked_user:";
    private static final String ATTEMPT_COUNT_PREFIX = "attempt_count:";

    @Autowired
    private StringRedisTemplate redisTemplate;

    public boolean authenticate(String username, String password) {
        // 检查用户是否被锁定
        if (isUserLocked(username)) {
            throw new RuntimeException("用户已被锁定,请稍后再试。");
        }

        // 验证用户密码
        boolean isValidPassword = checkPassword(username, password);
        if (isValidPassword) {
            resetAttemptCount(username); // 重置错误次数
            return true; // 登录成功
        } else {
            incrementAttemptCount(username); // 增加错误次数
            return false; // 登录失败
        }
    }

    private boolean isUserLocked(String username) {
        String key = LOCKED_USER_PREFIX + username;
        return redisTemplate.hasKey(key); // 如果用户被锁定,返回 true
    }

    private boolean checkPassword(String username, String password) {
        // TODO: 实现密码验证逻辑
        return "your_password".equals(password); // 示例验证
    }

    private void incrementAttemptCount(String username) {
        String key = ATTEMPT_COUNT_PREFIX + username;
        Integer count = Integer.valueOf(redisTemplate.opsForValue().get(key, 0)); // 获取当前失败次数
        count++;
        redisTemplate.opsForValue().set(key, count.toString(), 1, TimeUnit.DAYS); // 每日重置

        if (count >= 5) {
            lockUser(username); // 锁定用户
        }
    }

    private void resetAttemptCount(String username) {
        String key = ATTEMPT_COUNT_PREFIX + username;
        redisTemplate.delete(key); // 删除该用户的错误尝试次数
    }

    private void lockUser(String username) {
        String key = LOCKED_USER_PREFIX + username;
        redisTemplate.opsForValue().set(key, "locked", 30, TimeUnit.MINUTES); // 锁定用户30分钟
    }
}
代码说明
  1. authenticate(String username, String password): 主要方法,用于处理用户名和密码的验证。
  2. isUserLocked(String username): 检查用户是否已被锁定。
  3. checkPassword(String username, String password): 验证用户输入的密码是否正确。
  4. incrementAttemptCount(String username): 增加错误尝试次数,并在必要时锁定用户。
  5. resetAttemptCount(String username): 重置用户的错误尝试次数。
  6. lockUser(String username): 锁定用户,禁止其在一定时间内登录。

4. 流程图

下面是实现的流程图:

flowchart TD
    A[用户输入密码] --> B{验证密码}
    B -- 正确 --> C[登录成功]
    B -- 错误 --> D[记录错误次数]
    D --> E{错误是否达到5次}
    E -- 是 --> F[锁定用户]
    E -- 否 --> G[继续尝试]

5. 关系图

对于我们存储到 Redis 的数据,我们可以用以下 ER 图表示:

erDiagram
    USERS {
        String username PK
        String password
        Boolean locked
    }
    ATTEMPTS {
        String username FK
        Integer attempts
    }

总结

通过以上步骤,我们实现了一个简单的用户登录时的密码错误次数限制功能,当用户输入错误密码五次时会被锁定。使用 Redis 作为缓存存储,可以有效地提高性能。希望这篇文章能帮助你更好地理解如何在应用中实现安全策略。如果你有更多的疑问或需要进一步的帮助,请随时提出!