如何使用JSESSIONID手动加载Java会话?

时间:2009-09-30 17:33:53

标签: java session java-ee servlets httpsession

我有一个处理多部分表单帖子的servlet。帖子实际上是由嵌入页面的Flash文件上传组件制作的。在某些浏览器中,Flash生成的POST不包含JSESSIONID,这使得我无法在帖子期间从会话中加载某些信息。

Flash上​​传组件确实在特殊表单字段中包含cookie和会话信息。使用此表单字段,我实际上可以检索JSESSIONID值。问题是,我不知道如何使用此JSESSIONID值手动加载该特定会话。

编辑 - 基于ChssPly76的解决方案,我创建了以下 HttpSessionListener 实现:

    @Override
    public void sessionCreated(final HttpSessionEvent se) {
        final HttpSession session = se.getSession();
        final ServletContext context = session.getServletContext();
        context.setAttribute(session.getId(), session);
    }

    @Override
    public void sessionDestroyed(final HttpSessionEvent se) {
        final HttpSession session = se.getSession();
        final ServletContext context = session.getServletContext();
        context.removeAttribute(session.getId());
    }

ServletContext 的所有会话添加为由其唯一ID映射的属性。我可以在上下文中放置一个会话映射,但它似乎是多余的。请发表有关此决定的任何想法。接下来,我将以下方法添加到我的servlet以通过id解析会话:

    private HttpSession getSession(final String sessionId) {
        final ServletContext context = getServletContext();
        final HttpSession session = (HttpSession) context.getAttribute(sessionId);
        return session;
    }

5 个答案:

答案 0 :(得分:23)

没有API可以按ID检索会话。

但是,您可以在Web应用程序中实现session listener并手动维护由id键入的会话映射(会话ID可通过session.getId()检索)。然后,您将能够检索到您想要的任何会话(而不是像其他人建议的那样欺骗容器替换当前会话)

答案 1 :(得分:2)

一种安全的方法是在cookie中设置jsession id - 这比在url中设置它更安全。

将其设置为cookie后,您可以使用

以正常方式检索会话
request.getSession();

method.setRequestHeader("Cookie", "JSESSIONID=88640D6279B80F3E34B9A529D9494E09");

答案 2 :(得分:1)

servlet规范中没有办法,但您可以尝试:

  • 在Flash提出的请求中手动设置cookie

  • 或正如Taylor L刚刚建议的那样,我正在输入并添加jsessionid参数作为URI的路径。

这两种方法都会将您的应用程序绑定到运行类似于Tomcat的servlet容器上;我想其中大部分都是。两者都需要您的Flash小程序向页面询问其cookie,这可能会产生JavaScript依赖性。

答案 3 :(得分:0)

这是一篇非常好的帖子。我在使用会话侦听器继续向上下文添加会话时看到的一个潜在问题是,它可能会变得很胖,具体取决于您拥有的并发会话数。然后是监听器的Web服务器配置的所有额外工作。

那么对于一个更简单的解决方案来说,这是怎么回事。我确实实现了这个并且效果很好。因此,在加载Flash上​​载对象的页面上,将会话和sessionid存储为应用程序对象中的键值对,然后将该会话ID作为post参数传递给上载页面。在上载页面上,查看该sessionid是否已经在应用程序中,是这样使用该会话,否则,从请求中获取该会话。此外,然后继续从应用程序中删除该密钥以保持一切清洁。

在swf页面上:

application.setAttribute(session.getId(), session);

然后在上传页面上:

String sessid = request.getAttribute("JSESSIONID");
HttpSession sess = application.getAttribute(sessid) == null ?
        request.getSession() :
        (HttpSession)application.getAttribute(sessid);
application.removeAttribute(sessid);

非常好的解决方案的家伙。谢谢你。

答案 4 :(得分:0)

如果您使用的是Tomcat,则直接询问tomcat(但这很难看)。我打赌其他网络服务器还有其他hacky解决方案。

它使用“Manager”界面的实例来管理会话。让它变得丑陋的是我没有找到一个好的公共界面来加入,所以我们必须使用反射来获得经理。

下面是一个上下文监听器,它在上下文启动时抓取该管理器,然后可用于获取Tomcat会话。

public class SessionManagerShim implements ServletContextListener {
    static Manager manager;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            manager = getManagerFromServletContextEvent(sce);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        manager = null;
    }

    private static Manager getManagerFromServletContextEvent(ServletContextEvent sce) throws NoSuchFieldException, IllegalAccessException {
        // Step one - get the ApplicationContextFacade (Tomcat loves facades)
        ApplicationContextFacade contextFacade = (ApplicationContextFacade)sce.getSource();

        // Step two - get the ApplicationContext the facade wraps
        Field appContextField = ApplicationContextFacade.class.getDeclaredField("context");
        appContextField.setAccessible(true);
        ApplicationContext applicationContext = (ApplicationContext)
                appContextField.get(contextFacade);

        // Step three - get the Context (a tomcat context class) from the facade
        Field contextField = ApplicationContext.class.getDeclaredField("context");
        contextField.setAccessible(true);
        Context context = (Context) contextField.get(applicationContext);

        // Step four - get the Manager. This is the class Tomcat uses to manage sessions
        return context.getManager();
    }

    public static Session getSession(String sessionID) throws IOException {
        return manager.findSession(sessionID);
    }
}

您可以在web.xml中将其添加为侦听器,它应该可以正常工作。

然后你可以这样做以获得一个会话。