[英]How can I manually load a Java session using a JSESSIONID?
我有一个处理多部分表单帖子的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;
}
没有用于按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依赖。
这是一篇非常好的帖子。 我在使用会话侦听器继续向上下文添加会话时看到的一个潜在问题是,它可能会变得很胖,具体取决于您拥有的并发会话数。 然后为侦听器配置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”界面的实例来管理会话。 让它变得丑陋的是我没有找到一个好的公共接口来加入,所以我们必须使用反射来获取经理。
下面是一个上下文监听器,它在上下文启动时抓取该管理器,然后可用于获取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中将其添加为侦听器,它应该可以正常工作。
然后你可以这样做以获得一个会话。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.