如何获取序列化的tomcat HttpSession以重新填充spring SessionRegistry

Posted

技术标签:

【中文标题】如何获取序列化的tomcat HttpSession以重新填充spring SessionRegistry【英文标题】:How to get serialized tomcat HttpSession to repopulate spring SessionRegistry 【发布时间】:2018-03-08 00:29:50 【问题描述】:

我执行以下操作:

    登录到我的 spring 应用程序(例如,以用户“admin”的身份) 停止 tomcat 现在我看到会话被序列化为 sessions.ser 文件 我重启tomcat sessions.ser 文件消失了(我猜它在服务器启动期间被反序列化了?) 现在我发送一个需要登录用户的请求(如 在第 1 步中,即我在之前已经登录的浏览器中按 F5,所以我猜请求会沿着 jSessionId 等发送) 调试的时候可以观察到spring是如何成功加载SecurityContext的

HttpSessionSecurityContextRepository.readSecurityContextFromSession

使用存储的会话信息(它是一个 UsernamePasswordAuthenticationToken 包含一个包含 Principal 等的身份验证对象,因此获得自定义用户对象似乎是可能的)

    Spring 接受请求,即无需重新登录并发送适当的响应

但是,当尝试使用SessionRegistry 列出登录用户时

for (Object principal : sessionRegistry.getAllPrincipals()) 
            MyCustomUser myCustomUser = (MyCustomUser) principal;
            ClientQueryDetails client = clientQuery.getDetails(myCustomUser 
                    .getClientId()).get();
            List<SessionInformation> sessions = sessionRegistry.getAllSessions(
                    principal, false);
            for (SessionInformation sessionInformation : sessions) 
                result.add(new SessionInfo(client.getName(), myCustomUser 
                        .getUsername(), sessionInformation.getSessionId(),
                        sessionInformation.getLastRequest()));
            
        

正如我通常用来可视化当前活动的用户/会话一样,它是

为什么 Spring 现在不将这些 Principal 添加到 SessionRegistry 中? 我可以/应该以某种方式手动完成吗?

我读过https://github.com/spring-projects/spring-security/issues/2062,听起来这样做是个坏主意。

似乎也相关Getting logged in users with sessionRegistry not work when manually authenticate

我也找到了http://forum.spring.io/forum/spring-projects/web/71503-spring-not-restoring-persistent-sessions-to-session-registry

总结一下我的问题:

    为什么spring不将序列化的会话信息重新添加到SessionRegistry? 查询SessionRegistry 以向用户(即登录用户)显示所有活动会话是否正确? 编辑 是的,这绝对是 SessionRegisty 的目的:https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#list-authenticated-principals

    我应该手动将Principals 添加到 SessionRegistry 吗? 编辑 https://github.com/spring-projects/spring-security/issues/2062 提供了手动读取会话到 SessionRegistry 的不同方法,但是这样做似乎有一些注意事项。

    sessions.ser 中的 Session 被反序列化到何处以及如何准确地被反序列化,spring 从何处获得它?或者换句话说,session-information是如何从sessions.ser文件中获取到spring的SecurityContext的?尤其是怎么从tomcat“交”给spring的?

【问题讨论】:

#4:sessions.ser是Tomcat保存的HttpSession,与Spring无关。 Spring可以通过调用getAttribute()获取信息。但是,对于登录用户,Spring 也可以调用HttpServletRequest.getUserPrincipal()。要确切了解它的作用,请查看 Spring 源代码。 SessionRegistry 是当前附加用户的内存映射。当您关闭tomcat并在启动它时清空时,这显然会被破坏。如果您想要不同,请改用持久的SessionRegistry 【参考方案1】:

对于在 SessionRegistry 中看不到 Sessions 但拥有有效 Sessions(即登录用户)的问题,我的解决方案是简单地在服务器重启时删除 SESSIONS.ser 文件

因此,所有用户都必须重新登录,并相应地填充 SessionRegistry。由于我没有迫切需要保持会话保持活跃,这对我来说是一个很好的解决方案。

【讨论】:

以上是关于如何获取序列化的tomcat HttpSession以重新填充spring SessionRegistry的主要内容,如果未能解决你的问题,请参考以下文章

如何通过Java代码获取tomcat服务器的绝对路径

Java项目部署到tomcat上,我想知道如何获取项目中web-info的路径..

Tomcat 启动日志 - 严重:错误 filterStart 如何获取堆栈跟踪?

tomcat 报错 反序列化异常

如何获取 Grails/Tomcat Webapp 的当前工作目录?

如何使用 Tomcat 9 在 servlet req.getRemoteAddr() 中获取 ipv4 [关闭]