如何通过JSESSIONID加载Java HttpSession?

18

我想通过 JSESSIONID 获取 Java 的 HttpSession,这是否可行?如果是,该如何实现?

3个回答

33

基本上,您需要使用HttpSessionListener自己手动收集所有内容,并将其存储在Map中。

@WebListener
public class HttpSessionCollector implements HttpSessionListener {
    private static final Map<String, HttpSession> SESSIONS = new ConcurrentHashMap<>();

    @Override
    public void sessionCreated(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        SESSIONS.put(session.getId(), session);
    }


    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        SESSIONS.remove(event.getSession().getId());
    }

    public static HttpSession find(String sessionId) {
        return SESSIONS.get(sessionId);
    }
}

然后,在任何你想要的地方,只需执行 HttpSessionCollector.find(sessionId) 即可获取相关的HttpSession


话虽如此,这是一种巨大的坏味道。当然有比这个更好的方法来解决实际的功能需求 ;) 正如我在你的后续问题中所评论的:

这是你第二次提出一个在现实世界中不应该被实践的问题。老实说,这一切都很可疑。你认为在服务端获取与JSESSONID相关联的HttpSession并在客户端获取JSESSIONID值是“the”解决方案的问题是什么?在一个新的问题中详细阐述,你会得到正确方法的答案。

认真对待。我们不是在嘲笑你,我们只是想帮助你走向正确的方向,以避免你的项目/网站因安全漏洞和不良做法而崩溃,或者导致你被解雇。


也许我可以解释一下为什么我发现自己问了同样的问题,你可以解释一下为什么这不是我想要的:我假设我的服务器应该将详细信息存储在HTTPSession中,并将其sessionID(HttpSession.getId())返回给客户端,以便客户端可以将其存储在cookie中。然后客户端可以在几天后提供cookie给服务器,以再次使用相同的会话。但这需要服务器能够基于该会话ID检索HTTPSession,并/或以某种方式使其成为活动会话。但我仍在探索整个想法。(我正在使用GWT。) - murrayc
@murrayc:默认情况下,如果用户在30分钟内没有任何操作,会话将超时。另请参见https://dev59.com/GnA75IYBdhLWcg3wy8Qi#3106909和https://dev59.com/x3I95IYBdhLWcg3wtwVe#2186072。 - BalusC
1
啊,我现在明白了,HTTPSession(或者是在Tomcat中的实现,或者其他什么东西)会自动设置JSESSIONID cookie,并在用户关闭浏览器之前(但在此之前)确保HTTPSession具有该cookie中的JSESSIONID。所以我不需要这样做。我也明白了,我不想使用普通的JSESSIONID cookie来持续跨浏览器会话登录,因为a)那不是它的用途,b)那将不有效率。所以我将使用单独的cookie。 - murrayc
3
@BalusC Servlet规范并没有明确说明在不属于请求线程的情况下使用HttpSession对象是有效的,因此您不应该保留这些对象。最好只需在集合中保留sessionId和您自己的一些数据即可。背景:一些容器会重新创建或回收HttpSession对象,因此您不能在其上进行同步,参见https://dev59.com/KWkw5IYBdhLWcg3wkLb2, https://forum.hibernate.org/viewtopic.php?f=7&t=934936,https://forums.oracle.com/message/2973388 - mikewse

2
您可以按照 BalusC 的回答进行操作,但是这样的设施存在于不同用户之间的安全漏洞,这是一个显然的问题。您不应该将此类功能集成到您的应用程序中。

1

不,API 不允许这样做。

我想说的更多,但这就是全部了。


是的,API允许这样做,而且就是这样。 - user207421

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