Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 479 Vote(s) - 3.46 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can I have list of all users logged in (via spring security) my web application

#1
I'm using spring security in my web application, and now I want to have a list of all users who are logged in my program.

How can I have access to that list? Aren't they already kept somewhere within spring framework? Like ***SecurityContextHolder*** or ***SecurityContextRepository***?
Reply

#2
For accessing the list of all logged in users you need to inject SessionRegistry instance to your bean.

@Autowired
@Qualifier("sessionRegistry")
private SessionRegistry sessionRegistry;

And then using injcted SessionRegistry you can access the list of all principals:

List<Object> principals = sessionRegistry.getAllPrincipals();

List<String> usersNamesList = new ArrayList<String>();

for (Object principal: principals) {
if (principal instanceof User) {
usersNamesList.add(((User) principal).getUsername());
}
}

But before injecting session registry you need to define session management part in your spring-security.xml (look at [Session Management section in Spring Security reference documentation][1]) and in concurrency-control section you should set alias for session registry object (*session-registry-alias*) by which you will inject it.

<security:http access-denied-page="/error403.jsp" use-expressions="true" auto-config="false">
<security:session-management session-fixation-protection="migrateSession" session-authentication-error-url="/login.jsp?authFailed=true">
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.html" session-registry-alias="sessionRegistry"/>
</security:session-management>

...
</security:http>


[1]:

[To see links please register here]

Reply

#3
In JavaConfig, it would look like this:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
// ...
http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());
}

@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}

@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
}



With the calling code looking like this:

public class UserController {
@Autowired
private SessionRegistry sessionRegistry;

public void listLoggedInUsers() {
final List<Object> allPrincipals = sessionRegistry.getAllPrincipals();

for(final Object principal : allPrincipals) {
if(principal instanceof SecurityUser) {
final SecurityUser user = (SecurityUser) principal;

// Do something with user
System.out.println(user);
}
}
}
}


Note that `SecurityUser` is my own class which implements `UserDetails`.
Reply

#4
Please correct me if I'm wrong too.

I think @Adam's and @elysch`s answer is incomplete. I noticed that there are needed to add listener:

servletContext.addListener(HttpSessionEventPublisher.class);
to

public class AppInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) {
...
servletContext.addListener(HttpSessionEventPublisher.class);
}

with security conf:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
// ...
http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());
}

@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}

And then you will get current online users!
Reply

#5
Please correct me if I'm wrong.

I think [@Adam's][1] answer is incomplete. I noticed that sessions already expired in the list were appearing again.

public class UserController {
@Autowired
private SessionRegistry sessionRegistry;

public void listLoggedInUsers() {
final List<Object> allPrincipals = sessionRegistry.getAllPrincipals();

for (final Object principal : allPrincipals) {
if (principal instanceof SecurityUser) {
final SecurityUser user = (SecurityUser) principal;

List<SessionInformation> activeUserSessions =
sessionRegistry.getAllSessions(principal,
/* includeExpiredSessions */ false); // Should not return null;

if (!activeUserSessions.isEmpty()) {
// Do something with user
System.out.println(user);
}
}
}
}
}

Hope it helps.


[1]:

[To see links please register here]

Reply

#6
You need to inject `SessionRegistry` (as mentioned eariler) and then you can do it in one pipeline like this:

public List<UserDetails> findAllLoggedInUsers() {
return sessionRegistry.getAllPrincipals()
.stream()
.filter(principal -> principal instanceof UserDetails)
.map(UserDetails.class::cast)
.collect(Collectors.toList());
}
Reply

#7
Found this note to be quite important and relevant:

> "[21] Authentication by mechanisms which perform a redirect after
> authenticating (such as form-login) will not be detected by
> SessionManagementFilter, as the filter will not be invoked during the
> authenticating request. Session-management functionality has to be
> handled separately in these cases."

[To see links please register here]


Also, apparently a lot of people have troubles getting _sessionRegistry.getAllPrincipals()_ returning something different from an empty array. In my case, I fixed it by adding the _sessionAuthenticationStrategy_ to my custom _authenticationFilter_:


@Bean
public CustomUsernamePasswordAuthenticationFilter authenticationFilter() throws Exception {
...

authenticationFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
}

@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}

//cf.

[To see links please register here]

public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
List<SessionAuthenticationStrategy> stratList = new ArrayList<>();
SessionFixationProtectionStrategy concStrat = new SessionFixationProtectionStrategy();
stratList.add(concStrat);
RegisterSessionAuthenticationStrategy regStrat = new RegisterSessionAuthenticationStrategy(sessionRegistry());
stratList.add(regStrat);
CompositeSessionAuthenticationStrategy compStrat = new CompositeSessionAuthenticationStrategy(stratList);
return compStrat;
}

Reply

#8
Similar to @rolyanos solution, mine for me always works:

**- for the controller**


@RequestMapping(value = "/admin")
public String admin(Map<String, Object> model) {

if(sessionRegistry.getAllPrincipals().size() != 0) {
logger.info("ACTIVE USER: " + sessionRegistry.getAllPrincipals().size());
model.put("activeuser", sessionRegistry.getAllPrincipals().size());
}
else
logger.warn("EMPTY" );

logger.debug(log_msg_a + " access ADMIN page. Access granted." + ANSI_RESET);
return "admin";
}


**- for the front end**

<tr th:each="activeuser, iterStat: ${activeuser}">
<th><b>Active users: </b></th> <td align="center" th:text="${activeuser}"></td>
</tr>

**- for spring confing**

@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}

@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}


@Override
protected void configure(HttpSecurity http) throws Exception {

http.logout()
.logoutSuccessUrl("/home")
.logoutUrl("/logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");


http.authorizeRequests()
.antMatchers("/", "/home")
.permitAll()

.antMatchers("/admin")
.hasRole("ADMIN")
.anyRequest()
.authenticated()

.and()
.formLogin()
.loginPage("/home")
.defaultSuccessUrl("/main")
.permitAll()
.and()
.logout()
.permitAll();

http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());

http.authorizeRequests().antMatchers("/webjars/**").permitAll();

http.exceptionHandling().accessDeniedPage("/403");
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through