webentwicklung-frage-antwort-db.com.de

Wie kann ich eine Java-Sitzung manuell mit einer JSESSIONID laden?

Ich habe ein Servlet, das einen mehrteiligen Formularposten behandelt. Der Beitrag wird tatsächlich von einer in die Seite eingebetteten Flash-Datei-Upload-Komponente erstellt. In einigen Browsern enthält der von Flash generierte POST keine JSESSIONID, wodurch es mir unmöglich ist, während des Posts bestimmte Informationen aus der Sitzung zu laden. 

Die Flash-Upload-Komponente enthält Cookie- und Sitzungsinformationen in einem speziellen Formularfeld. Mit diesem Formularfeld kann ich tatsächlich den JSESSIONID-Wert abrufen. Das Problem ist, ich weiß nicht, wie ich mit diesem JSESSIONID-Wert diese bestimmte Sitzung manuell laden kann.

Edit - Basierend auf der Lösung von ChssPly76 habe ich die folgende HttpSessionListener -Implementierung erstellt:

    @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());
    }

Dadurch werden alle Sitzungen zum ServletContext als Attribute hinzugefügt, die ihren eindeutigen IDs zugeordnet sind. Ich könnte stattdessen eine Karte von Sitzungen in den Kontext einfügen, aber es scheint überflüssig zu sein. Bitte posten Sie Ihre Gedanken zu dieser Entscheidung. Als Nächstes füge ich meinem Servlet die folgende Methode hinzu, um die Sitzung nach ID aufzulösen:

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

Es gibt keine API zum Abrufen der Sitzung nach ID.

Sie können jedoch einen Sitzungslistener in Ihre Webanwendung implementieren und manuell eine von ID eingegebene Zuordnung von Sitzungen verwalten (Sitzungs-ID ist über session.getId () ) abrufbar. Sie können dann jede gewünschte Sitzung abrufen (anstatt den Container dazu zu bringen, Ihre aktuelle Sitzung durch andere zu ersetzen, wie von anderen vorgeschlagen).

23
ChssPly76

Ein sicherer Weg, dies zu tun, besteht darin, die Jsession-ID im Cookie festzulegen. Dies ist viel sicherer als das Setzen in der URL.

Sobald es als Cookie gesetzt ist, können Sie die Sitzung auf normale Weise mit abrufen 

request.getSession();

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

Es gibt keine Möglichkeit in der Servlet-Spezifikation, aber Sie könnten versuchen:

  • manuelles Setzen des Cookies in der Anforderung von Flash

  • oder als Taylor L zu tun, schlug nur vor, als ich den Pfad des URI eingab und den Parameter jsessionid hinzufügte.

Beide Methoden verbinden Ihre App mit der Ausführung in einem Servlet-Container, der sich wie Tomcat verhält. Ich denke, die meisten von ihnen tun es. Für beide wird auch verlangt, dass das Flash-Applet die Seite nach seinen Cookies fragt, wodurch möglicherweise eine JavaScript-Abhängigkeit entsteht.

1
Andrew Duffy

Wenn Sie Tomcat verwenden, fragen Sie Tomcat direkt (aber es ist hässlich). Ich wette, es gibt andere harte Lösungen für andere Webserver.

Es verwendet eine Instanz der "Manager" -Schnittstelle zur Verwaltung der Sitzungen. Was es hässlich macht, ist, dass ich keine nette öffentliche Benutzeroberfläche gefunden habe, an die ich mich anschließen kann. Daher müssen wir Reflection verwenden, um den Manager zu erreichen.

Nachfolgend finden Sie einen Kontextlistener, der diesen Manager beim Kontextstart erfasst und anschließend zum Abrufen der Tomcat-Sitzung verwendet werden kann.

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

Sie können dies in Ihrer web.xml als Listener hinzufügen und es sollte funktionieren.

Dann könnten Sie dies tun, um eine Sitzung zu erhalten.

0
Sam Sieber

Dies ist ein wirklich guter Beitrag. Ein potenzielles Problem bei der Verwendung des Sitzungslisteners zum Hinzufügen von Sitzungen zum Kontext ist, dass er je nach Anzahl der gleichzeitigen Sitzungen ziemlich fett werden kann. Und dann die gesamte zusätzliche Arbeit für die Webserver-Konfiguration für den Listener.

Wie wäre es damit für eine viel einfachere Lösung. Ich habe das umgesetzt und es funktioniert ziemlich gut. Speichern Sie also auf der Seite, die das Flash-Upload-Objekt lädt, die Sitzung und die Sitzungs-ID als Schlüssel/Wert-Paar im Anwendungsobjekt, und übergeben Sie diese Sitzungs-ID als Post-Parameter an die Upload-Seite. Auf der Upload-Seite können Sie feststellen, ob diese Sessionid bereits in der Anwendung enthalten ist. Diese Session wird verwendet, andernfalls rufen Sie die aus der Anforderung ab. Fahren Sie dann fort und entfernen Sie den Schlüssel aus der Anwendung, um alles sauber zu halten.

Auf der SWF-Seite:

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

Dann auf der Upload-Seite:

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

Sehr schöne Lösung Jungs. Danke dafür.

0
Garfield