Spring security spring安全登录/注销的日志记录
我试图找到一种方法,当用户通过SpringSecurity进行身份验证时,持久化db记录。同样,当他们注销或超时时,我想用那个时间更新那个记录。我一直在尝试使用AuthenticationSuccessHandler进行登录处理,使用LogoutSuccessHandler进行注销处理。但是,当我使用它时,我的URL会在它似乎中断后重定向 以下是我到目前为止的情况:Spring security spring安全登录/注销的日志记录,spring-security,spring-boot,Spring Security,Spring Boot,我试图找到一种方法,当用户通过SpringSecurity进行身份验证时,持久化db记录。同样,当他们注销或超时时,我想用那个时间更新那个记录。我一直在尝试使用AuthenticationSuccessHandler进行登录处理,使用LogoutSuccessHandler进行注销处理。但是,当我使用它时,我的URL会在它似乎中断后重定向 以下是我到目前为止的情况: @Component public class MyLoginSuccessHandler implements Authenti
@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
s。您可以使用JavaEEHttpSessionEvent
捕获它们。但是,如果您想访问与Spring相关的bean(例如Spring身份验证),则必须添加HttpSessionListener
,它将Java EE事件转换为Spring事件:HttpSessionEventPublisher
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
与成功处理程序相比,此方法具有一些优势:- 当您使用程序性注销(例如通过
)时,它也起作用HttpServletRequest.logout()
- 当您通过url注销时,它不会中断过滤链
另请参见我也有同样的问题。使用
时,不会调用successhandler
。因此,您必须在defaultsuccessurl
函数中重定向到所需的Url。尝试:onAuthenticationSuccess
@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
。但我不知道是否有注销事件。@DaveSyer目前没有。见和。AuthenticationSuccessEvent
<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,"/"); } }
- 当您使用程序性注销(例如通过