сессии - user session java




Как я могу вручную загрузить сеанс Java с помощью JSESSIONID? (4)

У меня есть сервлет, который обрабатывает многостраничную запись. Сообщение фактически создается компонентом загрузки 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:

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

API не может получить сеанс по id.

Однако вы можете использовать прослушиватель сеанса в своем веб-приложении и вручную поддерживать карту сеансов с ключом по идентификатору (идентификатор сеанса извлекается через session.getId() ). Затем вы сможете получить любой сеанс, который вы хотите (в отличие от обмана контейнера в замену вашей текущей сессии на него, как и другие)


Безопасный способ сделать это - установить id jsession в файл cookie - это намного безопаснее, чем устанавливать его в URL-адресе.

Как только он настроен как файл cookie, вы можете восстановить сеанс обычным способом, используя

request.getSession();

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

Если вы используете Tomcat, вы спрашиваете tomcat напрямую (но это уродливо). Бьюсь об заклад, есть и другие хакерские решения для других веб-серверов.

Он использует экземпляр интерфейса «Менеджер» для управления сеансами. Что делает его уродливым, так это то, что я не нашел приятный публичный интерфейс, чтобы иметь возможность подключиться, поэтому мы должны использовать отражение, чтобы получить менеджера.

Ниже представлен прослушиватель контекста, который захватывает этого менеджера при запуске контекста, а затем может использоваться для получения сеанса 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, и он должен работать.

Тогда вы можете сделать это, чтобы получить сеанс.


Это действительно хороший пост. Одна из потенциальных проблем, которые я вижу с использованием прослушивателя сеанса, чтобы добавлять сеансы в контекст, заключается в том, что он может быть довольно толстым в зависимости от количества одновременных сеансов, которые у вас есть. И затем вся дополнительная работа для настройки веб-сервера для слушателя.

Итак, как насчет этого для гораздо более простого решения. Я реализовал это, и он работает очень хорошо. Таким образом, на странице, загружающей объект загрузки Flash, храните сеанс и sessionid в качестве пары ключ-значение в объекте приложения, а затем передайте этот идентификатор сеанса на страницу загрузки в качестве параметра post. На странице загрузки, посмотрите, есть ли этот сеанс уже в приложении, так что используйте этот сеанс, в противном случае получите тот из запроса. Кроме того, затем продолжайте и удалите этот ключ из приложения, чтобы все было чисто.

На странице 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);

Очень приятное решение. Спасибо за это.





httpsession