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



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



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

1078   5  

5 ответов:

для доступа к списку всех зарегистрированных пользователей вам необходимо ввести экземпляр 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());
    }
}

но прежде чем вводить реестр сеансов, вам нужно определить часть управления сеансами в вашей spring-security.xml (посмотрите на раздел управления сеансами в справочной документации по безопасности Spring) и в разделе управления параллелизмом вы следует установить псевдоним для объекта реестра сеанса (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>

в 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.

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

Я думаю @Адама!--5--> ответ неполный. Я заметил, что сеансы уже истек в списке появлялись снова.

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

надеюсь, что это помогает.

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

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

 servletContext.addListener(HttpSessionEventPublisher.class);

до

public class AppInitializer implements WebApplicationInitializer {

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

С безопасностью 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();
    }
}

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

вам нужно впрыснуть SessionRegistry (Как уже упоминалось eariler), а затем вы можете сделать это в одном конвейере, как это:

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

Comments

    Ничего не найдено.