복붙노트

[SPRING] 내 웹 애플리케이션에 (스프링 보안을 통해) 로그인 한 모든 사용자 목록을 어떻게 표시 할 수 있습니까?

SPRING

내 웹 애플리케이션에 (스프링 보안을 통해) 로그인 한 모든 사용자 목록을 어떻게 표시 할 수 있습니까?

내 웹 응용 프로그램에서 스프링 보안을 사용하고 있으며 지금은 내 프로그램에 로그인 한 모든 사용자의 목록을 갖고 싶습니다.

해당 목록에 어떻게 액세스 할 수 있습니까? 이미 스프링 프레임 워크 내에서 어딘가에 보관되어 있지 않습니까? SecurityContextHolder 또는 SecurityContextRepository와 같은가?

해결법

  1. ==============================

    1.로그인 한 모든 사용자 목록에 액세스하려면 Bean에 SessionRegistry 인스턴스를 주입해야합니다.

    로그인 한 모든 사용자 목록에 액세스하려면 Bean에 SessionRegistry 인스턴스를 주입해야합니다.

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

    그리고 injured 된 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 Security 참조 문서의 세션 관리 섹션 참조)에서 세션 관리 부분을 정의하고 동시성 제어 섹션에서 세션 레지스트리 객체 (session-registry- 별칭)을 입력합니다.

        <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>
    
  2. ==============================

    2.JavaConfig에서는 다음과 같이 보입니다.

    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를 구현하는 클래스입니다.

  3. ==============================

    3.내가 틀렸다면 나를 바로 잡아주세요.

    내가 틀렸다면 나를 바로 잡아주세요.

    나는 @ Adam의 대답이 불완전하다고 생각한다. 목록에서 이미 만료 된 세션이 다시 나타났습니다.

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

    희망이 도움이됩니다.

  4. ==============================

    4.내가 틀렸다면 나를 바로 잡아주세요.

    내가 틀렸다면 나를 바로 잡아주세요.

    나는 @ Adam 's와 @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();
        }
    }
    

    그리고 현재 온라인 사용자를 얻을 것입니다!

  5. ==============================

    5.SessionRegistry (앞서 언급했듯이)를 주입해야하며 다음과 같이 한 파이프 라인에서 수행 할 수 있습니다.

    SessionRegistry (앞서 언급했듯이)를 주입해야하며 다음과 같이 한 파이프 라인에서 수행 할 수 있습니다.

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

    6.이 메모는 매우 중요하고 관련성이 높은 것으로 나타났습니다.

    이 메모는 매우 중요하고 관련성이 높은 것으로 나타났습니다.

    https://docs.spring.io/spring-security/site/docs/3.1.x/reference/session-mgmt.html#d0e4399

    또한, 많은 사람들이 빈 배열과 다른 것을 반환하는 sessionRegistry.getAllPrincipals ()를 얻는 데 어려움을 겪고있는 것 같습니다. 필자의 경우에는 sessionAuthenticationStrategy를 내 customFilter에 추가하여 해결했습니다.

    @Bean
    public CustomUsernamePasswordAuthenticationFilter authenticationFilter() throws Exception {
    ...
    
      authenticationFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
    }
    
    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }
    
    //cf. https://stackoverflow.com/questions/32463022/sessionregistry-is-empty-when-i-use-concurrentsessioncontrolauthenticationstrate
    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;
    }
    
  7. ==============================

    7.@rolyanos 솔루션과 비슷하게, 저에게는 제 일이 항상 효과가 있습니다.

    @rolyanos 솔루션과 비슷하게, 저에게는 제 일이 항상 효과가 있습니다.

    - 컨트롤러 용

    @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";
    }
    

    - 프런트 엔드 용

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

    - 봄용 구성

    @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");
    }
    
  8. from https://stackoverflow.com/questions/11271449/how-can-i-have-list-of-all-users-logged-in-via-spring-security-my-web-applicat by cc-by-sa and MIT license