文章目录
sql
2025-01-15 14:21:31.017
WARN 1972 --- [nio-8087-exec-8]
c.p.api.config.MyAuthenticationProvider
: 管理员:13524972741 登录失败:密码错误
解释:
- 时间戳:
2025-01-15 14:21:31.017
- 表示日志记录的时间。 - 日志级别:
WARN
- 表示这是一个警告级别的日志。 - 进程ID:
1972
- 表示发出日志的 Java 进程 ID。 - 线程信息:
[nio-8087-exec-8]
- 表示执行日志记录的线程。 - 类名:
c.p.api.config.MyAuthenticationProvider
- 表示发出日志的类的完整路径。 - 日志消息:
管理员:13524972741 登录失败:密码错误
- 表示具体的错误信息,管理员的用户名(这里是电话号码)登录失败,原因是密码错误。
格式化的目的:
通过换行,使得每部分信息都更加清晰独立,更容易阅读和理解。
1、URL
sql
http://127.0.0.1:8087/admin/signIn?username=???&password=???
json
{
"code": 1,
"msg": "用户名或密码错误"
}
1、AdminController
java
@Api(description = "后台用户管理")
@RestController
@RequestMapping("admin")
public class AdminController {
@PostMapping("signIn")
@ApiOperation("管理员账号密码登录swagger")
@PassToken
public BaseResult signIn(@RequestParam("username") String username,
@RequestParam("password") String password) {
return BaseResult.success();
}
}
- 我们发现signIn方法中没有任何逻辑,说明逻辑可能在 Spring Security 配置 中
3、AuthenticationProvider
java
package com.productQualification.api.config;
import com.productQualification.user.domain.Admin;
import com.productQualification.user.domain.Role;
import com.productQualification.user.service.AdminCacheService;
import com.productQualification.user.service.RoleCacheService;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
private static Map<String, Date> login = new HashMap<>();
private static final int LOGIN_INTERVAL = 5;//最小登录间隔
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Logger loggerAdmin = LoggerFactory.getLogger("ADMIN");
@Autowired
private AdminCacheService adminCacheService;
@Autowired
private RoleCacheService roleCacheService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 获取用户登录时输入的用户名
String username = authentication.getName();
checkLoginInterval(username);
// 根据用户名查询系统中的用户信息
Admin admin = adminCacheService.findByUsername(username);
// 如果用户列表为 null,说明查找用户功能出现异常,抛出 AuthenticationServiceException
if (null == admin) {
logger.warn("管理员:{} 登录失败:用户名错误", username);
throw new BadCredentialsException("用户名或密码错误");
}
// 锁定状态
if (Admin.LOCKED_BY_PASSWORD.equals(admin.getStatus())) {
if (new Date().after(DateUtils.addHours(admin.getLockedDate(), 24))) {//超过24小时自动解锁
admin.setStatus(Admin.NORMAL_STATUS);
admin.setPasswordAttemptCount(0);
admin.setLockedDate(null);
adminCacheService.save(admin);
} else {
logger.warn("管理员:{} 登录 登录失败:用户密码尝试次数过多 ", username);
throw new BadCredentialsException("用户密码尝试次数过多,请24小时后再尝试,或找领导解锁");
}
}
if (Admin.LOCKED_BY_LEADER.equals(admin.getStatus())) {
logger.warn("管理员:{} 登录 登录失败:用户已被上级锁定", username);
throw new BadCredentialsException("用户已被上级锁定");
}
// 密码对比
String password = (String) authentication.getCredentials();
if (admin.passwordUnMatches(password)) {
admin.setPasswordAttemptCount(admin.getPasswordAttemptCount() + 1);
if (admin.getPasswordAttemptCount() > Admin.PASSWORD_ATTEMPT_MAX_COUNT) {//密码尝试超过上限
admin.setStatus(Admin.LOCKED_BY_PASSWORD);
admin.setLockedDate(new Date());
adminCacheService.save(admin);
logger.warn("管理员:{} 登录 登录失败:用户密码尝试次数过多", username);
throw new BadCredentialsException("用户密码尝试次数过多,请24小时后再尝试,或找领导解锁");
}
adminCacheService.save(admin);
logger.warn("管理员:{} 登录失败:密码错误", username);
throw new BadCredentialsException("用户名或密码错误");
}
List<GrantedAuthority> authorities = new ArrayList<>();
List<Role> roles = roleCacheService.findRolesByAdminId(admin.getId());
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new UsernamePasswordAuthenticationToken(authentication, authentication.getCredentials(), authorities);
}
private void checkLoginInterval(String username) {
Date lastLoginDate = login.get(username);
if (null == lastLoginDate) {
login.put(username, new Date());
return;
}
if ((System.currentTimeMillis() - lastLoginDate.getTime())/1000 < LOGIN_INTERVAL) {
throw new BadCredentialsException("登录频率过高");
} else {
login.put(username, new Date());
}
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
}