[英]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.