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


替换UsernamePasswordAuthenticationFilter类

1. pom.xml

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

              &lt;overWrite&gt;false&lt;/overWrite&gt;
              &lt;outputDirectory&gt;${project.build.directory}/classes&lt;/outputDirectory&gt;
            &lt;/artifactItem&gt;
          &lt;/artifactItems&gt;
        &lt;/configuration&gt;
      &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;</pre><p><br/></p><p>2.重写<font color="#ff0000">FormLoginConfigurer</font>类,替换其中的<font color="#ff0000">UsernamePasswordAuthenticationFilter</font>为<font color="#ff0000">UsernamePasswordAuthenticationWithLogFilter</font>类</p><p><br/></p><pre>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;
    •    &amp;lt;legend&amp;gt;Please Login&amp;lt;/legend&amp;gt;
      
    •    &amp;lt;!-- use param.error assuming FormLoginConfigurer#failureUrl contains the query parameter error --&amp;gt;
      
    •    &amp;lt;c:if test="${param.error != null}"&amp;gt;
      
    •        &amp;lt;div&amp;gt;
      
    •            Failed to login.
      
    •            &amp;lt;c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}"&amp;gt;
      
    •              Reason: &amp;lt;c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" /&amp;gt;
      
    •            &amp;lt;/c:if&amp;gt;
      
    •        &amp;lt;/div&amp;gt;
      
    •    &amp;lt;/c:if&amp;gt;
      
    •    &amp;lt;!-- the configured LogoutConfigurer#logoutSuccessUrl is /login?logout and contains the query param logout --&amp;gt;
      
    •    &amp;lt;c:if test="${param.logout != null}"&amp;gt;
      
    •        &amp;lt;div&amp;gt;
      
    •            You have been logged out.
      
    •        &amp;lt;/div&amp;gt;
      
    •    &amp;lt;/c:if&amp;gt;
      
    •    &amp;lt;p&amp;gt;
      
    •    &amp;lt;label for="username"&amp;gt;Username&amp;lt;/label&amp;gt;
      
    •    &amp;lt;input type="text" id="username" name="username"/&amp;gt;
      
    •    &amp;lt;/p&amp;gt;
      
    •    &amp;lt;p&amp;gt;
      
    •    &amp;lt;label for="password"&amp;gt;Password&amp;lt;/label&amp;gt;
      
    •    &amp;lt;input type="password" id="password" name="password"/&amp;gt;
      
    •    &amp;lt;/p&amp;gt;
      
    •    &amp;lt;!-- if using RememberMeConfigurer make sure remember-me matches RememberMeConfigurer#rememberMeParameter --&amp;gt;
      
    •    &amp;lt;p&amp;gt;
      
    •    &amp;lt;label for="remember-me"&amp;gt;Remember Me?&amp;lt;/label&amp;gt;
      
    •    &amp;lt;input type="checkbox" id="remember-me" name="remember-me"/&amp;gt;
      
    •    &amp;lt;/p&amp;gt;
      
    •    &amp;lt;div&amp;gt;
      
    •        &amp;lt;button type="submit" class="btn"&amp;gt;Log in&amp;lt;/button&amp;gt;
      
    •    &amp;lt;/div&amp;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 ");
}
}
}


-----


如何记录SpringSecurity6.1中用户登录行为
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值