栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security 中基于ApplicationListener记录用户登录日志(含登录成功和登录失败)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security 中基于ApplicationListener记录用户登录日志(含登录成功和登录失败)

文章目录
  • 一、AuthenticationFailureListener(认证失败事件发布监听器)
  • 二、AuthencationSuccessListener(认证失败事件发布监听器)
  • 三、数据库脚本


SpringBoot项目集成Spring Security后,想要记录用户登录操作日志。其实在Spring Security中 org.springframework.security.authentication.event包下定义了发生认证时的所有事件类型,其中AbstractAuthenticationEvent是所有事件的父类,其它事件都继承于AbstractAuthenticationEvent。
其子类有

  • AbstractAuthenticationFailureEvent
  • AuthenticationFailureBadCredentialsEvent
  • AuthenticationFailureCredentialsExpiredEvent
  • AuthenticationFailureDisabledEvent
  • AuthenticationFailureExpiredEvent
  • AuthenticationFailureLockedEvent
  • AuthenticationFailureProviderNotFoundEvent
  • AuthenticationFailureProxyUntrustedEvent
  • AuthenticationFailureServiceExceptionEvent
  • AuthenticationSuccessEvent
  • InteractiveAuthenticationSuccessEvent

而AbstractAuthenticationFailureEvent又是所有认证异常发布事件的抽象类,这样就可以方便的分开成两个监听器;

一、AuthenticationFailureListener(认证失败事件发布监听器)
package com.chqiuu.erp.config.security.listener;

import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.*;
import org.springframework.stereotype.Component;


@Slf4j
@Component
public class AuthenticationFailureListener implements ApplicationListener {
    @Autowired
    private UserLoginLogService userLoginLogService;

    @Override
    public void onApplicationEvent(AbstractAuthenticationFailureEvent event) {
        String message;
        if (event instanceof AuthenticationFailureBadCredentialsEvent) {
            //提供的凭据是错误的,用户名或者密码错误
            message = "提供的凭据是错误的,用户名或者密码错误";
        } else if (event instanceof AuthenticationFailureCredentialsExpiredEvent) {
            //验证通过,但是密码过期
            message = "验证通过,但是密码过期";
        } else if (event instanceof AuthenticationFailureDisabledEvent) {
            //验证过了但是账户被禁用
            message = "验证过了但是账户被禁用";
        } else if (event instanceof AuthenticationFailureExpiredEvent) {
            //验证通过了,但是账号已经过期
            message = "验证通过了,但是账号已经过期";
        } else if (event instanceof AuthenticationFailureLockedEvent) {
            //账户被锁定
            message = "账户被锁定";
        } else if (event instanceof AuthenticationFailureProviderNotFoundEvent) {
            //配置错误,没有合适的AuthenticationProvider来处理登录验证
            message = "配置错误";
        } else if (event instanceof AuthenticationFailureProxyUntrustedEvent) {
            // 代理不受信任,用于Oauth、CAS这类三方验证的情形,多属于配置错误
            message = "代理不受信任";
        } else if (event instanceof AuthenticationFailureServiceExceptionEvent) {
            // 其他任何在AuthenticationManager中内部发生的异常都会被封装成此类
            message = "内部发生的异常";
        } else {
            message = "其他未知错误";
        }
        // 登录账号
        Object username = event.getAuthentication().getPrincipal();
        // 登录密码
        Object credentials = event.getAuthentication().getCredentials();
        UserLoginLogEntity loginLog = new UserLoginLogEntity();
        loginLog.setLoginIp( ServletUtil.getClientIP(Objects.requireNonNull(( (ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()), ""));
        loginLog.setAccount((String) username);
        loginLog.setLoginStatus(0);
        loginLog.setRemark(String.format("username:%s; pass:%s; message:%s", username, credentials, message));
        userLoginLogService.save(loginLog);
    }
}
二、AuthencationSuccessListener(认证失败事件发布监听器)
package com.chqiuu.erp.config.security.listener;

import com.chqiuu.erp.common.util.SecurityUtils;
import com.chqiuu.erp.user.dto.UserOnlineDto;
import com.chqiuu.erp.user.entity.UserLoginLogEntity;
import com.chqiuu.erp.user.service.UserLoginLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;


@Slf4j
@Component
public class AuthencationSuccessListener implements ApplicationListener {
    @Autowired
    private UserLoginLogService userLoginLogService;

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent event) {
        //用户通过输入用户名和密码登录成功
        // 登录账号
        UserOnlineDto useronline = (UserOnlineDto) event.getAuthentication().getPrincipal();
        UserLoginLogEntity loginLog = new UserLoginLogEntity();
        loginLog.setUserId(Long.valueOf(userOnline.getUserId()));
        loginLog.setAccount(userOnline.getAccount());
        loginLog.setLoginIp(SecurityUtils.getClientIp());
        loginLog.setLoginStatus(1);
        userLoginLogService.save(loginLog);
    }
}
三、数据库脚本
CREATE TABLE `user_login_log` (
  `log_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '日志唯一ID',
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户唯一ID',
  `account` varchar(50) DEFAULT NULL COMMENT '账号',
  `login_ip` varchar(20) DEFAULT NULL COMMENT '登录IP',
  `login_status` tinyint(4) DEFAULT NULL COMMENT '登录状态',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户登录日志记录表';
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/270963.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号