feat: track user login and logout timestamps in session management
This commit is contained in:
@@ -36,4 +36,10 @@ public class AppUser {
|
||||
inverseJoinColumns = @JoinColumn(name = "role_id")
|
||||
)
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
|
||||
@Column(name = "last_login_at")
|
||||
private java.time.LocalDateTime lastLoginAt;
|
||||
|
||||
@Column(name = "last_logout_at")
|
||||
private java.time.LocalDateTime lastLogoutAt;
|
||||
}
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.astalange.core.security;
|
||||
|
||||
import com.astalange.core.entity.AppUser;
|
||||
import com.astalange.core.repository.AppUserRepository;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.LogoutSuccessEvent;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class AuthenticationEventListener {
|
||||
|
||||
private final AppUserRepository userRepository;
|
||||
|
||||
public AuthenticationEventListener(AppUserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Transactional
|
||||
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
|
||||
String username = extractUsername(event.getAuthentication().getPrincipal());
|
||||
if (username != null) {
|
||||
userRepository.findByUsername(username).ifPresent(user -> {
|
||||
user.setLastLoginAt(LocalDateTime.now());
|
||||
userRepository.save(user);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Transactional
|
||||
public void onLogoutSuccess(LogoutSuccessEvent event) {
|
||||
if (event.getAuthentication() != null) {
|
||||
String username = extractUsername(event.getAuthentication().getPrincipal());
|
||||
if (username != null) {
|
||||
userRepository.findByUsername(username).ifPresent(user -> {
|
||||
user.setLastLogoutAt(LocalDateTime.now());
|
||||
userRepository.save(user);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Transactional
|
||||
public void onSessionDestroyed(HttpSessionDestroyedEvent event) {
|
||||
List<SecurityContext> contexts = event.getSecurityContexts();
|
||||
for (SecurityContext context : contexts) {
|
||||
if (context != null && context.getAuthentication() != null) {
|
||||
String username = extractUsername(context.getAuthentication().getPrincipal());
|
||||
if (username != null) {
|
||||
userRepository.findByUsername(username).ifPresent(user -> {
|
||||
if (user.getLastLogoutAt() == null || (user.getLastLoginAt() != null && user.getLastLogoutAt().isBefore(user.getLastLoginAt()))) {
|
||||
user.setLastLogoutAt(LocalDateTime.now());
|
||||
userRepository.save(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String extractUsername(Object principal) {
|
||||
if (principal instanceof UserDetails) {
|
||||
return ((UserDetails) principal).getUsername();
|
||||
} else if (principal instanceof String) {
|
||||
return (String) principal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE app_user ADD COLUMN last_login_at TIMESTAMP;
|
||||
ALTER TABLE app_user ADD COLUMN last_logout_at TIMESTAMP;
|
||||
Reference in New Issue
Block a user