feat: add active user session tracking and visualization in admin dashboard
AS Talange CI/CD Pipeline / Build & Run Unit Tests (push) Successful in 4m1s
AS Talange CI/CD Pipeline / Deploy to Test Environment (push) Successful in 5m34s

This commit is contained in:
2026-07-03 17:18:14 +02:00
parent 214ec08229
commit 19cee92437
4 changed files with 120 additions and 0 deletions
@@ -10,6 +10,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.session.HttpSessionEventPublisher;
@Configuration
@EnableWebSecurity
@@ -41,6 +44,10 @@ public class SecurityConfig {
.logout(logout -> logout
.logoutSuccessUrl("/login?logout")
.permitAll()
)
.sessionManagement(session -> session
.maximumSessions(100)
.sessionRegistry(sessionRegistry())
);
return http.build();
}
@@ -57,4 +64,14 @@ public class SecurityConfig {
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}
@@ -0,0 +1,37 @@
package com.astalange.web.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.stream.Collectors;
@Controller
@RequestMapping("/admin/sessions")
public class SessionController {
private final SessionRegistry sessionRegistry;
public SessionController(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
@GetMapping
@PreAuthorize("hasRole('ADMIN')")
public String viewSessions(Model model) {
List<Object> principals = sessionRegistry.getAllPrincipals();
List<String> activeUsers = principals.stream()
.filter(principal -> principal instanceof UserDetails)
.map(principal -> ((UserDetails) principal).getUsername())
.collect(Collectors.toList());
model.addAttribute("activeUsers", activeUsers);
model.addAttribute("activeCount", activeUsers.size());
return "admin/sessions";
}
}