SpringSecurity账号锁定 + 用户登入登出日志记录

代码如下

/**
 * 登陆成功监听
 *
 */
@Component
public class AuthenticationSuccessEventListener implements ApplicationListener<AuthenticationSuccessEvent> {

    @Resource
    private IUserService userService;

    @Resource
    private ILoginLogService loginLogService;

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent authenticationSuccessEvent) {
        //登录成功认证
        UserDetails userDetails = (UserDetails) authenticationSuccessEvent.getAuthentication().getPrincipal();
        String username = userDetails.getUsername();
        User newUser = new User();
        newUser.setActive("true");
        newUser.setUserAccounts(username);
        newUser.setFailsCount(0);
        userService.authenticationUpdateUser(username, newUser);
        //写入登录日志
        //Object details = authenticationSuccessEvent.getAuthentication().getDetails();//默认的details
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();//使用自定义的details,因为默认的Details只能获取到IP,和sessionid,才想着重写WebAuthenticationDetails
        MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails();
        User user = userService.findUser(username);
        LoginLog loginLog = new LoginLog();
        loginLog.setAccount(username);
        loginLog.setUserId(user.getId().toString());
        loginLog.setLoginIp(details.getRemoteAddress());
        loginLog.setLoginStatus("1");
        loginLogService.save(loginLog);
    }
}
/**
 * 登陆失败监听
 *
 */
@Component
public class AuthenticationFailureListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

    @Resource
    private IUserService userService;

    @Resource
    private ILoginLogService loginLogService;

    @Override
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent authenticationFailureBadCredentialsEvent) {
        String username = authenticationFailureBadCredentialsEvent.getAuthentication().getPrincipal().toString();
        User user = userService.findUser(username);
        //写入登录日志
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();//使用自定义的details
        MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails();
        LoginLog loginLog = new LoginLog();
        loginLog.setAccount(username);
        loginLog.setUserId(user.getId().toString());
        loginLog.setLoginIp(details.getRemoteAddress());
        loginLog.setLoginStatus("-1");
        loginLogService.save(loginLog);

        if (user != null) {
            // 用户失败次数
            Integer fails = user.getFailsCount();
            if(fails==null){
                fails = 0;
            }
            fails++;
            // 超出失败5次,停用账户
            if (fails >= 5) {
                User newUser = new User();
                newUser.setActive("false");
                newUser.setUserAccounts(username);
                newUser.setFailsCount(fails);
                userService.authenticationUpdateUser(username, newUser);
                throw new BaseException("您的账号已被锁定,请联系管理员...");
            } else {
                User newUser = new User();
                newUser.setFailsCount(fails);
                newUser.setUserAccounts(username);
                userService.authenticationUpdateUser(username, newUser);
            }
        }
    }
}

/**
 * 退出登陆监听
 *
 */
@Component
public class LogoutSuccessListener implements ApplicationListener<LogoutSuccessEvent> {
    @Resource
    private IUserService userService;

    @Resource
    private ILoginLogService loginLogService;

    @Override
    public void onApplicationEvent(LogoutSuccessEvent event) {
        //退出登录监听
        //写入登录日志
        UserDetails userDetails = (UserDetails) event.getAuthentication().getPrincipal();
        String username = userDetails.getUsername();
        User user = userService.findUser(username);

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();//使用自定义的details
        MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails();
        LoginLog loginLog = new LoginLog();
        loginLog.setAccount(username);
        loginLog.setUserId(user.getId().toString());
        loginLog.setLoginIp(details.getRemoteAddress());
        loginLog.setLoginStatus("0");
        loginLogService.save(loginLog);
    }
}

重写WebAuthenticationDetails

import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;

public class MyWebAuthenticationDetails extends WebAuthenticationDetails {

    public String getRemoteAddr() {
        return remoteAddr;
    }

    public void setRemoteAddr(String remoteAddr) {
        this.remoteAddr = remoteAddr;
    }

    private String remoteAddr;


    public MyWebAuthenticationDetails(HttpServletRequest request) {
        super(request);
        remoteAddr = request.getRemoteAddr();//得到来访者的IP地址
//        String requestUrl = request.getRequestURL().toString();//得到请求的URL地址
//        String requestUri = request.getRequestURI();//得到请求的资源
//        String queryString = request.getQueryString();//得到请求的URL地址中附带的参数
//        String remoteAddr = request.getRemoteAddr();//得到来访者的IP地址
//        String remoteHost = request.getRemoteHost();
//        int remotePort = request.getRemotePort();
//        String remoteUser = request.getRemoteUser();
//        String method = request.getMethod();//得到请求URL地址时使用的方法
//        String pathInfo = request.getPathInfo();
//        String localAddr = request.getLocalAddr();//获取WEB服务器的IP地址
//        String localName = request.getLocalName();//获取WEB服务器的主机名
    }
}

import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
@Component
public class MyWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, MyWebAuthenticationDetails> {
    @Override
    public MyWebAuthenticationDetails buildDetails(HttpServletRequest context) {
        return new MyWebAuthenticationDetails(context);
    }
}

最后的问题就是如何用自定义的 MyWebAuthenticationDetailsSource 代替系统默认的 WebAuthenticationDetailsSource,很简单,我们只需要在 SecurityConfig 中稍作定义即可

@Autowired
MyWebAuthenticationDetailsSource myWebAuthenticationDetailsSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            ...
            .and()
            .formLogin()
            .authenticationDetailsSource(myWebAuthenticationDetailsSource)
            ...
}

若代码中有写到
new WebAuthenticationDetailsSource().buildDetails(request)

那一定要改为new MyWebAuthenticationDetailsSource().buildDetails(request)

不然不起效

我的代码中是写了token认证,因为忽略了.buildDetails这里没有改成我们自定义的MyWebAuthenticationDetailsSource,找了半天bug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现用户登录登出日志记录,可以使用AOP(面向切面编程)技术,在用户登录退出的时候记录日志。 首先,需要在Spring配置文件中开启AOP支持: ``` <aop:aspectj-autoproxy /> ``` 然后,定义一个切面类来处理登录登出日志记录: ``` @Aspect public class LoginAspect { @Autowired private HttpServletRequest request; @Autowired private UserService userService; @Pointcut("execution(* com.example.controller.*Controller.login(..))") public void login() {} @Pointcut("execution(* com.example.controller.*Controller.logout(..))") public void logout() {} @AfterReturning("login()") public void afterLogin(JoinPoint joinPoint) { String username = (String) joinPoint.getArgs()[0]; User user = userService.getUserByUsername(username); String ip = request.getRemoteAddr(); String message = "User " + username + " logged in from " + ip; Log log = new Log(user.getId(), message); userService.saveLog(log); } @AfterReturning("logout()") public void afterLogout() { User user = (User) request.getSession().getAttribute("user"); String username = user.getUsername(); String ip = request.getRemoteAddr(); String message = "User " + username + " logged out from " + ip; Log log = new Log(user.getId(), message); userService.saveLog(log); } } ``` 在切面类中定义了两个切点,分别对应用户登录退出的方法。在用户登录后,通过参数获取用户名,再通过UserService获取用户信息和IP地址,最后记录日志。在用户退出后,从Session中获取用户信息,获取IP地址,记录日志。 最后,在Spring配置文件中配置切面类: ``` <bean class="com.example.aspect.LoginAspect" /> ``` 这样,在用户登录退出的时候,就会自动记录日志了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值