웹 응용 프로그램(스프링 보안을 통해)에 로그인한 모든 사용자의 목록을 확인하려면 어떻게 해야 합니까?
웹 응용 프로그램에서 스프링 보안을 사용하고 있는데 이제 프로그램에 로그인한 모든 사용자의 목록을 가지고 싶습니다.
어떻게 하면 그 목록에 접근할 수 있습니까?이미 스프링 틀 안에 어딘가에 보관되어 있지 않습니까?SecurityContextHolder나 SecurityContextRepository 같은 것?
로그인한 모든 사용자 목록에 액세스하려면 SessionRegistry 인스턴스를 빈에 주입해야 합니다.
@Autowired
@Qualifier("sessionRegistry")
private SessionRegistry sessionRegistry;
그런 다음 입력된 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 Management 섹션 참조). 동시성-제어 섹션에서 세션 레지스트리 개체(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
.
제가 틀렸다면 고쳐주세요.
@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);
}
}
}
}
}
도움이 되길 바랍니다.
저도 틀렸다면 고쳐주세요.
저는 @Adam's and @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();
}
}
그러면 현재 온라인 사용자를 확보할 수 있습니다!
주사를 놓아야 합니다.SessionRegistry
(이전에 언급된 대로) 그러면 다음과 같이 하나의 파이프라인에서 수행할 수 있습니다.
public List<UserDetails> findAllLoggedInUsers() {
return sessionRegistry.getAllPrincipals()
.stream()
.filter(principal -> principal instanceof UserDetails)
.map(UserDetails.class::cast)
.collect(Collectors.toList());
}
이 노트는 상당히 중요하고 관련성이 있음을 알 수 있었습니다.
"[21] 인증 후 리디렉션(폼 로그인 등)을 수행하는 메커니즘에 의한 인증은 SessionManagementFilter에 의해 감지되지 않습니다. 왜냐하면 인증 요청 중에 필터가 호출되지 않기 때문입니다.이 경우 세션 관리 기능은 별도로 처리해야 합니다."
https://docs.spring.io/spring-security/site/docs/3.1.x/reference/session-mgmt.html#d0e4399
또한 많은 사람들이 sessionRegistry.getAllPrincipals()가 빈 배열과 다른 것을 반환하는 데 문제가 있는 것 같습니다.저 같은 경우는 세션을 추가해서 고쳤습니다.Authentication Strategy to my custom authenticationFilter:
@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;
}
@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");
}
언급URL : https://stackoverflow.com/questions/11271449/how-can-i-have-list-of-all-users-logged-in-via-spring-security-my-web-applicat
'programing' 카테고리의 다른 글
woocommerce에 페이지당 제품 드롭다운 추가 (0) | 2023.10.08 |
---|---|
선호 속성 안드로이드: 의존성의 반대를 하는 방법? (0) | 2023.10.03 |
AngularJS UI 라우터:중첩된 명명된 뷰를 구성하는 방법은 무엇입니까? (0) | 2023.10.03 |
스크립트 실행을 무제한으로 설정 (0) | 2023.10.03 |
SQL에서 정수의 최대값을 얻으려면 어떻게 해야 합니까? (0) | 2023.10.03 |