c.p.api.config.MyAuthenticationProvider

文章目录

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;
    }
}
相关推荐
风逸hhh7 分钟前
python打卡day58@浙大疏锦行
开发语言·python
Q_9709563919 分钟前
java+vue+SpringBoo足球社区管理系统(程序+数据库+报告+部署教程+答辩指导)
java·开发语言·数据库
为了更好的明天而战43 分钟前
Java 中的 ArrayList 和 LinkedList 区别详解(源码级理解)
java·开发语言
JosieBook1 小时前
【Java编程动手学】Java中的数组与集合
java·开发语言·python
qq_589568101 小时前
element-plus按需自动导入的配置 以及icon图标不显示的问题解决
开发语言·javascript·ecmascript
lsx2024061 小时前
SQLite Select 语句详解
开发语言
Dovis(誓平步青云)2 小时前
基于探索C++特殊容器类型:容器适配器+底层实现原理
开发语言·c++·queue·适配器·stack
R-sz2 小时前
java流式计算 获取全量树形数据,非懒加载树,递归找儿
java·开发语言·windows
随意0232 小时前
Qt 事件
开发语言·qt
鸥梨菌Honevid2 小时前
Qt自定义控件(1)——QPaintEvent
开发语言·qt