密码遍历漏洞通常是由于系统返回的错误消息使得攻击者能够确定输入的用户名或密码是否正确而产生的。可使用Redis等缓存工具,防止攻击者通过大量尝试来遍历密码。
1.新增三个方法,分别是
登陆成功时删除掉错误的次数
登陆失败时记录错误的次数
登陆时判断次数是否锁定
以下为代码示例
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 LoginAttemptService {
private final int MAX_ATTEMPT = 5; // 最大尝试次数
private final long LOCK_DURATION_MINUTES = 15; // 锁定时间
@Autowired
private StringRedisTemplate redisTemplate;
public void loginSucceeded(String username) {
redisTemplate.delete(username + "_login_attempts");
}
public void loginFailed(String username) {
String key = username + "_login_attempts";
long attempts = redisTemplate.opsForValue().increment(key, 1);
redisTemplate.expire(key, LOCK_DURATION_MINUTES, TimeUnit.MINUTES);
if (attempts >= MAX_ATTEMPT) {
redisTemplate.opsForValue().set(username + "_locked", "true", LOCK_DURATION_MINUTES, TimeUnit.MINUTES);
}
}
public boolean isUserLocked(String username) {
return redisTemplate.hasKey(username + "_locked");
}
}
以下是登陆方法.关键代码为loginAttemptService的方法,根据实际情况修改即可
@PostMapping("login")
@ResponseBody
public Mess appLogin(@RequestBody User user) {
if (loginAttemptService.isUserLocked(user.getUsername())) {
return new Mess(20004, "账户已被锁定,请稍后再试!");
}
user = userService.login(user);
if (user == null) {
loginAttemptService.loginFailed(user.getUsername());
return new Mess(20003, "登陆失败,安全认证失败!");
}
loginAttemptService.loginSucceeded(user.getUsername());
String token = JwtUtil.generateToken(JwtUtil.signingKey, user);
return new Mess(0, token, user);
}
评论区