爆破,也就是通过海量的尝试,最终确定密码,人们设置密码具有习惯性,好记、简单、有象征等,也就有密码字典一说,但是该字典也是巨量的,但是相对于各种字母符号等组合就显得轻量非常多
在Java Spring Boot中,使用Redis实现账号密码防爆破是一种常见的安全措施。通过Redis的高性能和原子性操作,可以有效地限制用户在一定时间内的登录尝试次数,从而防止暴力破解攻击。以下是一个巧妙的实现方案:
1. 引入依赖
首先,在pom.xml
中引入Spring Boot的Redis依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置Redis
在application.properties
或application.yml
中配置Redis连接信息:
spring.redis.host=localhost
spring.redis.port=6379
3. 创建Redis工具类
创建一个Redis工具类,用于操作Redis中的登录尝试次数:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component
public class RedisLoginAttemptService {private static final String LOGIN_ATTEMPT_KEY_PREFIX = "login_attempt:";private static final int MAX_ATTEMPTS = 5; // 最大允许的登录尝试次数private static final long LOCK_TIME = 30 * 60; // 锁定时间,单位:秒@Autowiredprivate StringRedisTemplate redisTemplate;/*** 记录登录尝试** @param username 用户名* @return 当前尝试次数*/public int recordLoginAttempt(String username) {String key = LOGIN_ATTEMPT_KEY_PREFIX + username;Integer attempts = redisTemplate.opsForValue().increment(key, 1).intValue();if (attempts == 1) {redisTemplate.expire(key, LOCK_TIME, TimeUnit.SECONDS);}return attempts;}/*** 检查是否超过最大尝试次数** @param username 用户名* @return 是否超过最大尝试次数*/public boolean isBlocked(String username) {String key = LOGIN_ATTEMPT_KEY_PREFIX + username;Integer attempts = redisTemplate.opsForValue().get(key) == null ? 0 : Integer.parseInt(redisTemplate.opsForValue().get(key));return attempts != null && attempts >= MAX_ATTEMPTS;}/*** 重置登录尝试次数** @param username 用户名*/public void resetLoginAttempts(String username) {String key = LOGIN_ATTEMPT_KEY_PREFIX + username;redisTemplate.delete(key);}
}
4. 在登录逻辑中使用
在登录逻辑中使用上述工具类来限制登录尝试次数:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class LoginService {@Autowiredprivate RedisLoginAttemptService loginAttemptService;@Autowiredprivate UserRepository userRepository; // 假设有一个UserRepository用于验证用户public boolean login(String username, String password) {// 检查是否被锁定if (loginAttemptService.isBlocked(username)) {throw new RuntimeException("账号已被锁定,请稍后再试");}// 验证用户名和密码User user = userRepository.findByUsername(username);if (user == null || !user.getPassword().equals(password)) {// 记录登录尝试loginAttemptService.recordLoginAttempt(username);throw new RuntimeException("用户名或密码错误");}// 登录成功,重置登录尝试次数loginAttemptService.resetLoginAttempts(username);return true;}
}
5. 控制器层
在控制器层调用登录服务:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class LoginController {@Autowiredprivate LoginService loginService;@PostMapping("/login")public String login(@RequestParam String username, @RequestParam String password) {try {if (loginService.login(username, password)) {return "登录成功";}} catch (RuntimeException e) {return e.getMessage();}return "登录失败";}
}
6. 也可以加入ip封禁
启动应用后,存在ip胡乱请求,也可以加入ip封禁,当ip存在大量登录失败请求,可以将ip进行限制,比如1个小时最多进行5~7次登录,超过拉进黑名单,接下来半个小时或一天都不再校验他的登录请求,但是每次也返回一个请求成功的返回码或者错误的登录令牌,欺骗爆破工具,真真假假,虚虚实实,使它爆破难度激增