首页 > 其他分享 >如何记录SpringSecurity6.1中用户登录行为

如何记录SpringSecurity6.1中用户登录行为

时间:2023-12-05 09:35:54浏览次数:43  
标签:gt 登录 用户 lt SpringSecurity6.1 link import security loginLog


替换UsernamePasswordAuthenticationFilter类

1. pom.xml

    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
    </dependency>




     <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>unpack</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>unpack</goal>
            </goals>
            <configuration>
              <artifactItems>                
                <artifactItem>
                  <groupId>org.springframework.security</groupId>
                  <artifactId>spring-security-config</artifactId>

                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/classes</outputDirectory>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>


2.重写FormLoginConfigurer类,替换其中的UsernamePasswordAuthenticationFilterUsernamePasswordAuthenticationWithLogFilter


package org.springframework.security.config.annotation.web.configurers;

import com.sparkmap.platform.security.filter.UsernamePasswordAuthenticationWithLogFilter;

import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * Adds form based authentication. All attributes have reasonable defaults making all
 * parameters are optional. If no {@link #loginPage(String)} is specified, a default login
 * page will be generated by the framework.
 *
 * <h2>Security Filters</h2>
 *
 * The following Filters are populated
 *
 * <ul>
 * <li>{@link UsernamePasswordAuthenticationFilter}</li>
 * </ul>
 *
 * <h2>Shared Objects Created</h2>
 *
 * The following shared objects are populated
 *
 * <ul>
 * <li>{@link AuthenticationEntryPoint}</li>
 * </ul>
 *
 * <h2>Shared Objects Used</h2>
 *
 * The following shared objects are used:
 *
 * <ul>
 * <li>{@link org.springframework.security.authentication.AuthenticationManager}</li>
 * <li>{@link RememberMeServices} - is optionally used. See {@link RememberMeConfigurer}
 * </li>
 * <li>{@link SessionAuthenticationStrategy} - is optionally used. See
 * {@link SessionManagementConfigurer}</li>
 * <li>{@link DefaultLoginPageGeneratingFilter} - if present will be populated with
 * information from the configuration</li>
 * </ul>
 *
 * @author Rob Winch
 * @author Shazin Sadakath
 * @since 3.2
 */
public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
        AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {

    /**
     * Creates a new instance
     * @see HttpSecurity#formLogin()
     */
    public FormLoginConfigurer() {
        super(new UsernamePasswordAuthenticationWithLogFilter(), null); // 改为自己写的类
        usernameParameter("username");
        passwordParameter("password");
    }

    /**
     * <p>
     * Specifies the URL to send users to if login is required. If used with
     * {@link EnableWebSecurity} a default login page will be generated when this
     * attribute is not specified.
     * </p>
     *
     * <p>
     * If a URL is specified or this is not being used in conjunction with
     * {@link EnableWebSecurity}, users are required to process the specified URL to
     * generate a login page. In general, the login page should create a form that submits
     * a request with the following requirements to work with
     * {@link UsernamePasswordAuthenticationFilter}:
     * </p>
     *
     * <ul>
     * <li>It must be an HTTP POST</li>
     * <li>It must be submitted to {@link #loginProcessingUrl(String)}</li>
     * <li>It should include the username as an HTTP parameter by the name of
     * {@link #usernameParameter(String)}</li>
     * <li>It should include the password as an HTTP parameter by the name of
     * {@link #passwordParameter(String)}</li>
     * </ul>
     *
     * <h2>Example login.jsp</h2>
     *
     * Login pages can be rendered with any technology you choose so long as the rules
     * above are followed. Below is an example login.jsp that can be used as a quick start
     * when using JSP's or as a baseline to translate into another view technology.
     *
     * <pre>
     * <!-- loginProcessingUrl should correspond to FormLoginConfigurer#loginProcessingUrl. Don't forget to perform a POST -->
     * &lt;c:url value="/login" var="loginProcessingUrl"/&gt;
     * &lt;form action="${loginProcessingUrl}" method="post"&gt;
     *    &lt;fieldset&gt;
     *        &lt;legend&gt;Please Login&lt;/legend&gt;
     *        &lt;!-- use param.error assuming FormLoginConfigurer#failureUrl contains the query parameter error --&gt;
     *        &lt;c:if test="${param.error != null}"&gt;
     *            &lt;div&gt;
     *                Failed to login.
     *                &lt;c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}"&gt;
     *                  Reason: &lt;c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" /&gt;
     *                &lt;/c:if&gt;
     *            &lt;/div&gt;
     *        &lt;/c:if&gt;
     *        &lt;!-- the configured LogoutConfigurer#logoutSuccessUrl is /login?logout and contains the query param logout --&gt;
     *        &lt;c:if test="${param.logout != null}"&gt;
     *            &lt;div&gt;
     *                You have been logged out.
     *            &lt;/div&gt;
     *        &lt;/c:if&gt;
     *        &lt;p&gt;
     *        &lt;label for="username"&gt;Username&lt;/label&gt;
     *        &lt;input type="text" id="username" name="username"/&gt;
     *        &lt;/p&gt;
     *        &lt;p&gt;
     *        &lt;label for="password"&gt;Password&lt;/label&gt;
     *        &lt;input type="password" id="password" name="password"/&gt;
     *        &lt;/p&gt;
     *        &lt;!-- if using RememberMeConfigurer make sure remember-me matches RememberMeConfigurer#rememberMeParameter --&gt;
     *        &lt;p&gt;
     *        &lt;label for="remember-me"&gt;Remember Me?&lt;/label&gt;
     *        &lt;input type="checkbox" id="remember-me" name="remember-me"/&gt;
     *        &lt;/p&gt;
     *        &lt;div&gt;
     *            &lt;button type="submit" class="btn"&gt;Log in&lt;/button&gt;
     *        &lt;/div&gt;
     *    &lt;/fieldset&gt;
     * &lt;/form&gt;
     * </pre>
     *
     * <h2>Impact on other defaults</h2>
     *
     * Updating this value, also impacts a number of other default values. For example,
     * the following are the default values when only formLogin() was specified.
     *
     * <ul>
     * <li>/login GET - the login form</li>
     * <li>/login POST - process the credentials and if valid authenticate the user</li>
     * <li>/login?error GET - redirect here for failed authentication attempts</li>
     * <li>/login?logout GET - redirect here after successfully logging out</li>
     * </ul>
     *
     * If "/authenticate" was passed to this method it update the defaults as shown below:
     *
     * <ul>
     * <li>/authenticate GET - the login form</li>
     * <li>/authenticate POST - process the credentials and if valid authenticate the user
     * </li>
     * <li>/authenticate?error GET - redirect here for failed authentication attempts</li>
     * <li>/authenticate?logout GET - redirect here after successfully logging out</li>
     * </ul>
     * @param loginPage the login page to redirect to if authentication is required (i.e.
     * "/login")
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    @Override
    public FormLoginConfigurer<H> loginPage(String loginPage) {
        return super.loginPage(loginPage);
    }

    /**
     * The HTTP parameter to look for the username when performing authentication. Default
     * is "username".
     * @param usernameParameter the HTTP parameter to look for the username when
     * performing authentication
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public FormLoginConfigurer<H> usernameParameter(String usernameParameter) {
        getAuthenticationFilter().setUsernameParameter(usernameParameter);
        return this;
    }

    /**
     * The HTTP parameter to look for the password when performing authentication. Default
     * is "password".
     * @param passwordParameter the HTTP parameter to look for the password when
     * performing authentication
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public FormLoginConfigurer<H> passwordParameter(String passwordParameter) {
        getAuthenticationFilter().setPasswordParameter(passwordParameter);
        return this;
    }

    /**
     * Forward Authentication Failure Handler
     * @param forwardUrl the target URL in case of failure
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
        failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
        return this;
    }

    /**
     * Forward Authentication Success Handler
     * @param forwardUrl the target URL in case of success
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
        successHandler(new ForwardAuthenticationSuccessHandler(forwardUrl));
        return this;
    }

    @Override
    public void init(H http) throws Exception {
        super.init(http);
        initDefaultLoginFilter(http);
    }

    @Override
    protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
        return new AntPathRequestMatcher(loginProcessingUrl, "POST");
    }

    /**
     * Gets the HTTP parameter that is used to submit the username.
     * @return the HTTP parameter that is used to submit the username
     */
    private String getUsernameParameter() {
        return getAuthenticationFilter().getUsernameParameter();
    }

    /**
     * Gets the HTTP parameter that is used to submit the password.
     * @return the HTTP parameter that is used to submit the password
     */
    private String getPasswordParameter() {
        return getAuthenticationFilter().getPasswordParameter();
    }

    /**
     * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared
     * object.
     * @param http the {@link HttpSecurityBuilder} to use
     */
    private void initDefaultLoginFilter(H http) {
        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
                .getSharedObject(DefaultLoginPageGeneratingFilter.class);
        if (loginPageGeneratingFilter != null && !isCustomLoginPage()) {
            loginPageGeneratingFilter.setFormLoginEnabled(true);
            loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter());
            loginPageGeneratingFilter.setPasswordParameter(getPasswordParameter());
            loginPageGeneratingFilter.setLoginPageUrl(getLoginPage());
            loginPageGeneratingFilter.setFailureUrl(getFailureUrl());
            loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl());
        }
    }

}


3.实现自己写的UsernamePasswordAuthenticationWithLogFilter

package com.ruitu.platform.security.filter;

import java.io.IOException;
import java.util.Date;

import com.alibaba.fastjson2.JSONObject;
import com.ruitu.platform.security.domain.LoginLog;
import com.ruitu.platform.security.domain.SecurityUser;
import com.ruitu.platform.security.enumeration.LoginStatus;
import com.ruitu.platform.security.service.LoginLogService;
import com.ruitu.platform.utils.ExceptionUtil;
import com.ruitu.platform.utils.RequestInfoUtil;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
* 扩展UsernamePasswordAuthenticationFilter类,实现日志功能
* 
*/
public class UsernamePasswordAuthenticationWithLogFilter extends UsernamePasswordAuthenticationFilter {

  private LoginLogService loginLogService = null;

  private ThreadLocal<Long> currentTime = new ThreadLocal<>();

  public LoginLogService getLoginLogService() {
    return loginLogService;
  }

  public void setLoginLogService(LoginLogService loginLogService) {
    this.loginLogService = loginLogService;
  }

  public UsernamePasswordAuthenticationWithLogFilter() {
    super();
  }

  public UsernamePasswordAuthenticationWithLogFilter(AuthenticationManager authenticationManager) {
    super(authenticationManager);
  }

  public UsernamePasswordAuthenticationWithLogFilter(AuthenticationManager authenticationManager, LoginLogService loginLogService) {
    super(authenticationManager);
    this.loginLogService = loginLogService;
  }

  public UsernamePasswordAuthenticationWithLogFilter(LoginLogService loginLogService) {
    this.loginLogService = loginLogService;
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    currentTime.set(System.currentTimeMillis());// 记录方法的执行时间
    return super.attemptAuthentication(request, response);
  }

  @Override
  protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    super.successfulAuthentication(request, response, chain, authResult);
    Date startTime = new Date();
    startTime.setTime(currentTime.get());
    currentTime.remove();
    //
    if (loginLogService != null) {
      SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
      String username = securityUser.getUsername();
      String password = obtainPassword(request);
      LoginLog loginLog = new LoginLog();
      loginLog.setStatus(LoginStatus.SUCCESS.name());
      loginLog.setResponseResult(JSONObject.toJSONString(authResult));
      loginLog.setUsername(username);
      loginLog.setPassword(password);
      loginLog.setBrowser(RequestInfoUtil.getBrowser(request));
      loginLog.setIp(RequestInfoUtil.getIp(request));
      loginLog.setRequestTime(startTime);
      loginLog.setCreateTime(new Date());
      loginLog.setResponseTime(loginLog.getCreateTime());
      loginLogService.recordLoginLog(loginLog);
    } else {
      System.out.println("-----------------------------------------:  successfulAuthentication ");
    }
  }

  @Override
  protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
    super.unsuccessfulAuthentication(request, response, failed);
    Date startTime = new Date();
    startTime.setTime(currentTime.get());
    currentTime.remove();
    if (loginLogService != null) {
      String username = obtainUsername(request);
      username = (username != null) ? username.trim() : "";
      String password = obtainPassword(request);
      LoginLog loginLog = new LoginLog();
      loginLog.setStatus(LoginStatus.FAIL.name());
      loginLog.setExceptionDetail(ExceptionUtil.getStackMsg(failed).substring(255));
      loginLog.setUsername(username);
      loginLog.setPassword(password);
      loginLog.setBrowser(RequestInfoUtil.getBrowser(request));
      loginLog.setIp(RequestInfoUtil.getIp(request));
      loginLog.setRequestTime(startTime);
      loginLog.setCreateTime(new Date());
      loginLog.setResponseTime(loginLog.getCreateTime());
      loginLogService.recordLoginLog(loginLog);
    } else {
      System.out.println("-----------------------------------------:  unsuccessfulAuthentication ");
    }
  }
}


-----

标签:gt,登录,用户,lt,SpringSecurity6.1,link,import,security,loginLog
From: https://www.cnblogs.com/gispathfinder/p/17876485.html

相关文章

  • Day19 Java 流程控制01:用户交互Scanner
    Java流程控制01:用户交互ScannerScanner对象之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类:Scanner类,可以通过它来获取用户的输入基本语法:Scannerscanner=newScanner(System.in);通过Scanner类的next()与nextLine()方......
  • 4.1 配置Mysql与注册登录模块(上)
    点击查看sql代码createdatabasekob;usekob;createtableuser(idint,usernamevarchar(100),passwordvarchar(100));mysql>showtables;+---------------+|Tables_in_kob|+---------------+|user|+---------------+1rowinset(0.00sec)......
  • MySQL系列之读写分离架构——Atlas介绍、安装配置、Atlas功能测试、生产用户要求、Atl
    文章目录1.Atlas介绍2.安装配置3.Atlas功能测试4.生产用户要求5.Atlas基本管理6.自动分表7.关于读写分离建议1.Atlas介绍Atlas是由Qihoo360,Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy0.8.2版本的基础上,对其......
  • uniapp获取用户信息
    新接口getUserProfileFn内置login,如果必须要login返回的参数要隔离开vue3书写要对按钮配置属性<button@click="logintou"data-eventsync="true"class="main-login-bottom">授权登录</button>——————————————————constapp=getApp()exportletloginFn......
  • 基于Java的养老院管理系统的设计与实现(亮点:多角色、登录验证码、留言反馈)
    养老院管理系统一、前言二、我的优势2.1自己的网站2.2自己的小程序(小蔡coding)2.3有保障的售后2.4福利三、开发环境与技术3.1MySQL数据库3.2Vue前端技术3.3SpringBoot框架3.4微信小程序四、功能设计4.1主要功能描述五、系统实现5.1养老院老人功能5.1.1饮食喜好5.1.2体......
  • umask永久修改用户创建文件权限
    Linux里永久设置用户创建文件权限的配置文件是/etc/profile。可以在该文件中添加umask命令来设置默认权限。具体操作步骤如下:打开/etc/profile文件:sudovi/etc/profile在文件末尾添加umask命令并设置默认权限例如设置默认权限为022:umask022保存文件并退出使配置文件生效:so......
  • 安装mysql报错:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (
    @目录当前状态报错解决办法:当前状态目前已经启动好mysql服务:systemctlstartmysqldsystemctlstatusmysqld生成临时密码grep'temporarypassword'/var/log/mysqld.log报错出现了报错:ERROR1045(28000):Accessdeniedforuser'root'@'localhost'(usingpass......
  • Instagram营销的社交互动:建立用户参与感
    Instagram营销的社交互动:建立用户参与感 简介:在当今社交媒体时代,Instagram已成为品牌和企业进行市场推广的重要渠道之一。然而,仅仅在Instagram上发布内容是不够的,你还需要通过社交互动来建立用户参与感。本文将探讨一些有效的策略,帮助你在Instagram上建立用户参与感,提升品牌知......
  • 【实用+干货】如何使用Clickhouse搭建百亿级用户画像平台看这一篇就够了
    背景如果你是用户,当你使用抖音、小红书的时候,假如平台能根据你的属性、偏好、行为推荐给你感兴趣的内容,那就能够为你节省大量获取内容的时间。如果你是商家,当你要进行广告投放的时候,假如平台推送的用户都是你潜在的买家,那你就可以花更少的钱,带来更大的收益。这两者背后都有一项......
  • Vue3用户代码片段
    1.defineComponent语法{ "Printtoconsole":{ "prefix":"vue3", "body":[ "<template>", "<divclass=\"container\">", "", "</div>&q......