Spring security spring安全登录/注销的日志记录

Spring security spring安全登录/注销的日志记录,spring-security,spring-boot,Spring Security,Spring Boot,我试图找到一种方法,当用户通过SpringSecurity进行身份验证时,持久化db记录。同样,当他们注销或超时时,我想用那个时间更新那个记录。我一直在尝试使用AuthenticationSuccessHandler进行登录处理,使用LogoutSuccessHandler进行注销处理。但是,当我使用它时,我的URL会在它似乎中断后重定向 以下是我到目前为止的情况: @Component public class MyLoginSuccessHandler implements Authenti

我试图找到一种方法,当用户通过SpringSecurity进行身份验证时,持久化db记录。同样,当他们注销或超时时,我想用那个时间更新那个记录。我一直在尝试使用AuthenticationSuccessHandler进行登录处理,使用LogoutSuccessHandler进行注销处理。但是,当我使用它时,我的URL会在它似乎中断后重定向

以下是我到目前为止的情况:

@Component
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {

    public MyLoginSuccessHandler() {
        super();
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        System.out.println("Logged In User " + (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
    }
}
要捕获注销事件,请执行以下操作:

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    public MyLogoutSuccessHandler() {
        super();
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {

        System.out.println("Logged OUT User " + (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
    }
}
我将我的安全性配置为:

@Configuration
@EnableWebMvcSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Autowired
    private MyLoginSuccessHandler myLoginSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
http
                .formLogin().failureUrl( "/login?error" )
                .successHandler(myLoginSuccessHandler)
                .defaultSuccessUrl( "/" )
                .loginPage( "/login" )
                .permitAll()
                .and()
                .logout().logoutRequestMatcher( new AntPathRequestMatcher( "/logout" ) )
                .permitAll();

        http
                .sessionManagement()
                .maximumSessions( 1 )
                .expiredUrl( "/login?expired" )
                .maxSessionsPreventsLogin( true )
                .and()
                .sessionCreationPolicy( SessionCreationPolicy.IF_REQUIRED )
                .invalidSessionUrl( "/" );

        http
                .authorizeRequests().anyRequest().authenticated();

        http
                .logout()
                .logoutSuccessHandler(myLogoutSuccessHandler)
                .logoutSuccessUrl( "/" );
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        auth.userDetailsService( customUserDetailsService ).passwordEncoder( encoder );
    }
}
如果我将
.defaultSuccessUrl(“/”)
放在.successHandler之前,则会调用该处理程序,但页面重定向不会发生,登录结果是/login的空白页面。类似地,用于登录/注销

有人能看到这里有什么问题吗

更新: 我添加了执行器和我自己的应用程序侦听器:

@Component
public class LoginListener implements ApplicationListener<AuthenticationSuccessEvent> {

    private static final Logger LOG = LoggerFactory.getLogger(LoginListener.class);

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent event) {
        UserDetails ud = (UserDetails) event.getAuthentication().getPrincipal();

        LOG.info("User " + ud.getUsername() + " logged in successfully");
    }
}
我还尝试通过listener处理:

@Component
public class LogoutListener implements ApplicationListener<SessionDestroyedEvent> {

    private static final Logger LOG = LoggerFactory.getLogger(LogoutListener.class);

    @Override
    public void onApplicationEvent(SessionDestroyedEvent event) {
        List<SecurityContext> lstSecurityContext = event.getSecurityContexts();
        UserDetails ud;
        for (SecurityContext securityContext : lstSecurityContext)
        {
            ud = (UserDetails) securityContext.getAuthentication().getPrincipal();
            LOG.debug("User " + ud.getUsername() + " logged OUT successfully");
        }
    }
}

这一个被调用,所以我确信注销会发生。

我在注销后做额外的事情时遇到了同样的问题,并通过以下方式解决了它:

  • 与您在更新方法中一样,我使用
    ApplicationListener
  • 但另外,您必须向部署描述符添加一个
    HttpSessionEventPublisher
    。原因见第页。简而言之:
    会话销毁事件是发生在Spring环境之外的JavaEE
    HttpSessionEvent
    s。您可以使用JavaEE
    HttpSessionListener
    捕获它们。但是,如果您想访问与Spring相关的bean(例如Spring身份验证),则必须添加
    HttpSessionEventPublisher
    ,它将Java EE事件转换为Spring事件:

    <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>
    

    与成功处理程序相比,此方法具有一些优势:

    • 当您使用程序性注销(例如通过
      HttpServletRequest.logout()
      )时,它也起作用
    • 当您通过url注销时,它不会中断过滤链


    另请参见

    我也有同样的问题。使用
    successhandler
    时,不会调用
    defaultsuccessurl
    。因此,您必须在
    onAuthenticationSuccess
    函数中重定向到所需的Url。尝试:

    @Component
    public class LoginListener implements ApplicationListener<AuthenticationSuccessEvent> {
    
      private static final Logger LOG = LoggerFactory.getLogger(LoginListener.class);
    
      private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
      @Override
      public void onApplicationEvent(AuthenticationSuccessEvent event) {
        UserDetails ud = (UserDetails) event.getAuthentication().getPrincipal();
    
        LOG.info("User " + ud.getUsername() + " logged in successfully");
        redirectStrategy.sendRedirect(request, response,"/");
      }
    }
    
    @组件
    公共类LoginListener实现ApplicationListener{
    私有静态最终记录器LOG=LoggerFactory.getLogger(LoginListener.class);
    private RedirectStrategy RedirectStrategy=新的DefaultRedirectStrategy();
    @凌驾
    ApplicationEvent上的公共无效(AuthenticationSuccessEvent事件){
    UserDetails ud=(UserDetails)event.getAuthentication().getPrincipal();
    LOG.info(“用户”+ud.getUsername()+“成功登录”);
    redirectStrategy.sendRedirect(请求、响应“/”);
    }
    }
    

    LogoutListener执行同样的操作,它应该可以工作(即使您不更改配置文件)。

    请参阅参考指南的一节。添加
    springbootstarteractor
    依赖项,并实现您自己的
    AuditEventRepository
    。您需要一个额外的
    LogoutHandler
    来发布注销的审核事件(我怀疑),但这就是您所需要的。好主意。或者只需收听
    AuthenticationSuccessEvent
    。但我不知道是否有注销事件。@DaveSyer目前没有。见和。
    <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>
    
    @Component
    public class AuthenticationApplicationListener {
    
      @EventListener
      public void handleSessionDestroyedEvent(SessionDestroyedEvent event) {
          List<SecurityContext> lstSecurityContext = event.getSecurityContexts();
          for (SecurityContext securityContext : lstSecurityContext) {
    
            //Try to find out, if this event is caused by a logout,
            //This is true, when the old session has been an authenticated one.
            Authentication auth = securityContext.getAuthentication();
            if (auth == null ||
                !auth.isAuthenticated() ||
                auth instanceof AnonymousAuthenticationToken) {
                return;
            }
    
            //do something
      }
    }
    
    @Component
    public class LoginListener implements ApplicationListener<AuthenticationSuccessEvent> {
    
      private static final Logger LOG = LoggerFactory.getLogger(LoginListener.class);
    
      private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
      @Override
      public void onApplicationEvent(AuthenticationSuccessEvent event) {
        UserDetails ud = (UserDetails) event.getAuthentication().getPrincipal();
    
        LOG.info("User " + ud.getUsername() + " logged in successfully");
        redirectStrategy.sendRedirect(request, response,"/");
      }
    }