[SPRING] 내 웹 애플리케이션에 (스프링 보안을 통해) 로그인 한 모든 사용자 목록을 어떻게 표시 할 수 있습니까?
SPRING내 웹 애플리케이션에 (스프링 보안을 통해) 로그인 한 모든 사용자 목록을 어떻게 표시 할 수 있습니까?
내 웹 응용 프로그램에서 스프링 보안을 사용하고 있으며 지금은 내 프로그램에 로그인 한 모든 사용자의 목록을 갖고 싶습니다.
해당 목록에 어떻게 액세스 할 수 있습니까? 이미 스프링 프레임 워크 내에서 어딘가에 보관되어 있지 않습니까? SecurityContextHolder 또는 SecurityContextRepository와 같은가?
해결법
-
==============================
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.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.내가 틀렸다면 나를 바로 잡아주세요.
내가 틀렸다면 나를 바로 잡아주세요.
나는 @ 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.내가 틀렸다면 나를 바로 잡아주세요.
내가 틀렸다면 나를 바로 잡아주세요.
나는 @ 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.SessionRegistry (앞서 언급했듯이)를 주입해야하며 다음과 같이 한 파이프 라인에서 수행 할 수 있습니다.
SessionRegistry (앞서 언급했듯이)를 주입해야하며 다음과 같이 한 파이프 라인에서 수행 할 수 있습니다.
public List<UserDetails> findAllLoggedInUsers() { return sessionRegistry.getAllPrincipals() .stream() .filter(principal -> principal instanceof UserDetails) .map(UserDetails.class::cast) .collect(Collectors.toList()); }
-
==============================
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.@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"); }
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
'SPRING' 카테고리의 다른 글
[SPRING] property-placeholder에 의해 생성 된 속성에 대한 프로그래밍 방식의 액세스 (0) | 2018.12.16 |
---|---|
[SPRING] Spring의 "자동 프록시를 사용할 수 없음"원인 추적 (0) | 2018.12.16 |
[SPRING] 스프링 기반 SockJS / STOMP 웹 소켓이있는 JSON 웹 토큰 (JWT) (0) | 2018.12.16 |
[SPRING] 클러스터 환경에서 실행되는 Spring Scheduled Task (0) | 2018.12.16 |
[SPRING] 스프링 MVC - 날짜 필드 바인딩 (0) | 2018.12.16 |