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

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

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; } 

没有用于按ID检索会话的API。

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

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

一旦将其设置为cookie,您就可以使用正常方式检索会话

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

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

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

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

这两种方法都会将您的应用程序与运行在类似Tomcat的servlet容器上运行; 我想他们中的大多数都这样做。 两者都需要您的Flash小程序向页面询问其cookie,这可能会产生JavaScript依赖性。

这是一个非常好的post。 我在使用会话侦听器继续向上下文添加会话时看到的一个潜在问题是,它可能会变得很胖,具体取决于您拥有的并发会话数。 然后是监听器的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); 

很好的解决方案的人。 谢谢你。

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

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

下面是一个上下文监听器,它在上下文启动时抓取该管理器,然后可以用于获取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中将其添加为侦听器,它应该可以正常工作。

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