2012-06-30 2 views
49

Я использую весеннюю безопасность в своем веб-приложении, и теперь я хочу иметь список всех пользователей, которые вошли в мою программу.Как я могу получить список всех зарегистрированных пользователей (через весеннюю безопасность) мое веб-приложение

Как я могу получить доступ к этому списку? Разве они уже не находятся где-то в весеннем контексте? Как SecurityContextHolder или SecurityContextRepository?

ответ

49

Для доступа к списку всех зарегистрированных пользователей вам необходимо ввести экземпляр SessionRegistry в свой компонент.

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

А затем с помощью injcted SessionRegistry вы можете получить доступ к списку всех принципалов:

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

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

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

Но перед инъекцией реестра сеанса необходимо определить управления сеансом роль в вашей весенней security.xml (смотреть на Session Management section in Spring Security reference documentation), а в секции управления параллелизмом вы должны установить псевдоним для объекта реестра сеанса (session-registry-alias), посредством которого вы будете вводить его.

<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> 
27

В JavaConfig, это будет выглядеть следующим образом:

@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()); 
    } 
} 

С вызывающий код вида:

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); 
      } 
     } 
    } 
} 

Обратите внимание, что SecurityUser мой собственный класс, который реализует UserDetails.

+11

Ответы, кажется, правильные, но для меня это всегда возвращается и пустая коллекция, любая идея? – azerafati

+3

Для записи класс ServletListenerRegistrationBean является частью Spring Boot, поэтому вам придется добавить зависимость с Spring Boot. В моей организации только Spring MVC и Spring Security одобрены для использования, поэтому я не могу использовать ваше решение (кстати, это выглядит потрясающе). Придется найти другой способ добиться этого. Благодаря! –

+0

@mailman да, я сохраняю сессию, и с этого сеанса я получаю список зарегистрированных пользователей –

6

Пожалуйста, исправьте меня, если я ошибаюсь.

Я думаю, @Adam's Ответ неполный. Я заметил там, где в списке уже истекли сеансы.

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); 
       } 
      } 
     } 
    } 
} 

Надеюсь, что это поможет.

5

Пожалуйста, исправьте меня, если я ошибаюсь.

Я думаю, что ответ Адама и @ elysch является неполным. Я заметил, что нужно добавить слушателя:

servletContext.addListener(HttpSessionEventPublisher.class); 

в

public class AppInitializer implements WebApplicationInitializer { 

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

с конф безопасности:

@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(); 
    } 
} 

И тогда вы получите текущие онлайн-пользователей!