¿Cómo puedo cargar manualmente una sesión de Java usando un JSESSIONID?


Tengo un servlet que maneja un post de formulario multiparte. La publicación en realidad está siendo hecha por un componente de carga de archivos Flash incrustado en la página. En algunos navegadores, la PUBLICACIÓN generada por Flash no incluye el JSESSIONID, lo que me impide cargar cierta información de la sesión durante la publicación.

El componente flash upload incluye información sobre cookies y sesiones dentro de un campo de formulario especial. Usando este campo de formulario, puedo recuperar el JSESSIONID valor. El problema es que no se como usar este valor JSESSIONID para cargar manualmente esa sesión específica.

Edit - Basado en la solución de ChssPly76, creé la siguiente implementación 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());
    }

Que agrega todas las sesiones al ServletContext como atributos mapeados por sus identificadores únicos. Podría poner un Mapa de sesiones en el contexto, pero parece redundante. Por favor, publique cualquier comentario sobre esta decisión. A continuación, añado el siguiente método a mi servlet para resolver la sesión por id:

    private HttpSession getSession(final String sessionId) {
        final ServletContext context = getServletContext();
        final HttpSession session = (HttpSession) context.getAttribute(sessionId);
        return session;
    }
Author: Eyal, 2009-09-30

5 answers

No hay ninguna API para recuperar la sesión por id.

Lo que puede hacer, sin embargo, es implementar un receptor de sesión en su aplicación web y mantener manualmente un mapa de sesiones con clave id (el id de sesión se puede recuperar a través de sesión.getId () ). A continuación, podrá recuperar cualquier sesión que desee (en lugar de engañar al contenedor para que reemplace su sesión actual con él como otros sugirieron)

 22
Author: ChssPly76,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-30 17:42:50

Una forma segura de hacerlo es establecer el id de jsession en la cookie - esto es mucho más seguro que configurarlo en la url.

Una vez que se establece como cookie, puede recuperar la sesión de la manera normal utilizando

request.getSession();

method.setRequestHeader("Cookie", "JSESSIONID=88640D6279B80F3E34B9A529D9494E09");
 2
Author: vanval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-19 13:16:49

No hay manera dentro de la especificación de servlet, pero podría intentar:

  • Configuración manual de la cookie en la solicitud realizada por Flash

  • O haciendo como Taylor L acaba de sugerir mientras estaba escribiendo y añadiendo el parámetro jsessionid la ruta del URI.

Ambos métodos vincularán su aplicación a la ejecución en un contenedor de servlet que se comporta como Tomcat; creo que la mayoría de ellos lo hacen. Ambos también requerirán que su applet de Flash le pida a la página sus cookies, lo que puede imponer una dependencia de JavaScript.

 1
Author: Andrew Duffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-30 17:40:23

Este es un post realmente bueno. Un problema potencial que veo con el uso del oyente de sesiones para seguir agregando sesiones al contexto es que puede ser bastante gordo dependiendo del número de sesiones simultáneas que tenga. Y luego todo el trabajo adicional para la configuración del servidor web para el oyente.

Entonces, qué tal esto para una solución mucho más simple. Implementé esto y funciona bastante bien. Por lo tanto, en la página que carga el objeto flash upload, almacene la sesión y el sessionid como un a continuación, pase ese id de sesión a la página de carga como parámetro post. El en la página de carga, ver si ese sessionid ya está en la aplicación, es así que utilice esa sesión, de lo contrario, obtener el de la solicitud. Además, a continuación, seguir adelante y quitar esa clave de la aplicación para mantener todo limpio.

En la página de swf:

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

Luego en la página de carga:

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

Muy buena solución chicos. Gracias por esto.

 0
Author: Garfield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-12 00:27:00

Si estás usando Tomcat, le preguntas a tomcat directamente (pero es feo). Apuesto a que hay otras soluciones hacky para otros servidores web.

Utiliza una instancia de la interfaz "Manager" para gestionar las sesiones. Lo que lo hace feo es que no he encontrado una interfaz pública agradable para poder engancharse, así que tenemos que usar la reflexión para obtener el gerente.

A continuación se muestra un oyente de contexto que agarra ese administrador en el inicio de contexto, y luego se puede usar para obtener el Tomcat Sesion.

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

Puede agregar esto como un oyente en su web.xml y debería funcionar.

Entonces podría hacer esto para obtener una sesión.

 0
Author: Sam Sieber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 18:20:51