在Spring中如何销毁另一个用户的会话?

12

在我的应用程序中,我有一个管理员可以删除用户。所以当我从管理员会话中删除用户时,我希望被删除的用户应该自动注销。 我知道我要删除的用户的会话ID,但我不知道如何使用会话ID使会话失效。

我想要类似这样的东西:invalidate(SessionId);

有没有任何可能性?我认为可以使用过滤器并在每个请求上检查数据库,但是否有另一种方式,我不需要在每个HTTP请求上检查数据库呢?

谢谢:D


请问您如何获取用户的会话 ID? - Bramanta
4个回答

8

我认为可以使用Spring Security基础设施来解决问题,使用SessionRegistry类。

您需要在web.xml中注册HttpSessionEventPublisher

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

在您的Spring配置中,声明SessionRegistry。
<bean id="sessionRegistry"
     class="org.springframework.security.core.session.SessionRegistryImpl" />

在您的管理控制台中,您必须使用SessionRegistry来检索用户的SessionInformation并调用expireNow。在用户的下一个请求中,servlet过滤器应使HttpSession过期。有关其工作原理的一些说明,请参阅SessionInformation的javadoc。
如果这有所帮助,请告诉我们。

我遇到了问题,我调用了*sessionRegistry.registerNewSession(String session, Object principal)来注册会话,但是当我删除用户时,我正确地获取了会话并在控制器中调用了sessionInformation.expireSession()*,但它没有起作用。用户的会话仍然在运行。 - Josema
2
我再次阅读了文档,我认为您还需要将<session-management ...>添加到Spring安全配置文件的<http>部分中。希望这能有所帮助。 - LaurentG
为什么不把这个加入答案中呢? - Alex78191

7
// to end a session of a user:
List<SessionInformation> sessions = sessionRegistryImpl.getAllSessions(user, false);
sessionRegistryImpl.getSessionInformation(sessions.get(0).getSessionId()).expireNow();

// note: you can get all users and their corresponding session Ids: 
List<Object> users = sessionRegistryImpl.getAllPrincipals();
List<String> sessionIds = new ArrayList<>(users.size());

for (Object user: users) {
    List<SessionInformation> sessions = sessionRegistryImpl.getAllSessions(user, false);
    sessionIds.add(sessions.get(0).getSessionId());
}

我必须做LaurentG写的吗? - Alex78191
@Alex78191,我们的答案基本相同。在这两种情况下,您需要调用expireNow方法。 - zygimantus
我应该在web.xml中注册HttpSessionEventPublisher并声明SessionRegistry吗? - Alex78191
记不得了。我使用的不是web.xml,而是Java配置。 - zygimantus
我相信你可能想要像上面那样使用户的会话过期,但同时也将其删除(removeSessionInformation(sessionid)。 - Woodchuck

0
除了如上所述的使用户过期之外,您可能还希望将其从注册表中删除:
// expire and remove the user's sessions from Spring session registry
List<Object> principals = sessionRegistry.getAllPrincipals();
for (Object principal : principals) {
    List<SessionInformation> sessions = sessionRegistry.getAllSessions(principal, true);
    for (SessionInformation sessionInfo : sessions) {
        if (authentication.getPrincipal().equals(sessionInfo.getPrincipal())) {
           if (!sessionInfo.isExpired()) sessionInfo.expireNow();
           sessionRegistry.removeSessionInformation(sessionInfo.getSessionId());
        }
    }
}

如果使用XML配置来连接您的Spring Session Registry,它可能看起来像这样:

<beans:bean id="sessionRegistry"
    class="org.springframework.security.core.session.SessionRegistryImpl" />

0

除了@LaurentG所建议的内容外,您的Spring配置文件还需要添加以下内容:

<session-management>
    <concurrency-control session-registry-alias="sessionRegistry" />
</session-management>

为了使其工作。此外,@zygimantus的答案可用于访问会话数据。


<concurrency-control session-registry-alias="sessionRegistry" /> is the same as <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/> - Alex78191

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接