通过管理员 Spring Security 注销用户

Posted

技术标签:

【中文标题】通过管理员 Spring Security 注销用户【英文标题】:Log out user by admin Spring Security 【发布时间】:2017-11-05 16:29:07 【问题描述】:

我希望您能帮助我了解如何实现此功能: admin 使用 sessionRegistry.getAllPrincipals() 获取所有登录用户,然后可以注销某人。 我知道如何注销当前用户(session.invalidate()),但不知道如何强制注销其他用户。

这段代码让我所有登录的用户

public List<User> getAllLoggedInUsers() 
    List<Object> principals = sessionRegistry.getAllPrincipals();
    List<User> usersNamesList = new ArrayList<>();
    for (Object principal : principals) 
        if (principal instanceof org.springframework.security.core.userdetails.User) 
            usersNamesList.add(dao.findByLogin(((org.springframework.security.core.userdetails.User) principal).getUsername()));
        
    
    return usersNamesList;

非常感谢。

编辑1:我想要下一个:管理员选择一个用户,禁止它(更改数据库中的信息),然后如果该用户处于活动状态 - 将他注销。

【问题讨论】:

我猜,最简单的解决方案是重启应用服务器。这将终止所有会话。 @KrishnaKuntala 我不需要)我只是想弄清楚如何实现这个功能。 【参考方案1】:

首先,你需要一个sessionRegistry,它可以获取所有会话并注册新会话:

@Bean
SessionRegistry sessionRegistry() 
    return new SessionRegistryImpl();

其次,您需要启用sessionRegistry 并使用ConcurrentSessionFilter 来控制无效会话。

http
 .sessionManagement() 
    .maximumSessions(-1)
    .sessionRegistry(sessionRegistry());

-1 表示没有限制,但这将自动注册ConcurrentSessionFilterRegisterSessionAuthenticationStrategy。基于上次的spring security配置,如果你使用xml或者旧版本的spring security,请找this page寻求帮助。

ConcurrentSessionFilter 将从sessionRegistry 获取会话,并在会话到期时注销。

最后一件事是在尝试通过用户获取会话并使用户的会话到期时向您的应用程序注入相同的 sessionRegistry bean。

您可以通过调用 getAllSessions(Object principal, boolean includeExpiredSessions) 方法列出用户的会话,该方法返回 SessionInformation 对象列表。您还可以通过在 SessionInformation 实例上调用 expireNow() 来使用户的会话到期。当用户返回应用程序时,他们将被阻止继续。

【讨论】:

哇,这更容易了。我不知道 sessionRegistry 可以提供所有会话。所以我自己实现了。我创建了实现 HttpSessionListener 的类 SessionCounterListener,每次创建会话时,我都会将它添加到列表中。所以任何时候我都可以获得活动会话的列表。【参考方案2】:

假设你这样尝试。

public void logoutUser(HttpServletRequest httpRequest, HttpServletResponse httpResponse) 
        Authentication auth = getAuthentication();

    for (int i = 0; i < logoutHandler.length; i++) 
        logoutHandler[i].logout(httpRequest, httpResponse, auth);
    

        AnonymousAuthenticationToken aat = new AnonymousAuthenticationToken("your key you use",
                "anonymousUser", new GrantedAuthority[]
                new GrantedAuthorityImpl("ROLE_ANONYMOUS"));
        ((SecurityContext)SecurityContextHolder.getContext()).setAuthentication(aat);
    

您还可以在关注post1 和post2 中找到更多方法。

还可以获取当前登录的用户并设置SecurityContextHolder.getContext().setAuthentication(null)

【讨论】:

是的,这就是使当前活动用户会话无效的方法。但我需要使不是当前但仍处于活动状态(登录)的用户会话无效。 @Paren'Vacya 确实提到他知道如何注销当前用户。

以上是关于通过管理员 Spring Security 注销用户的主要内容,如果未能解决你的问题,请参考以下文章

Spring security - 无法注销

防止 Spring Security 在登录/注销后进行 302 重定向

Spring security logout - 仅在登录用户触发注销时添加消息

java spring boot / spring security(HttpSecurity)中的会话到期时如何自动注销

spring security - 如何让另一个用户注销

Spring Security基本配置(登录,注销,权限,记住我,注解)