Подтвердить что ты не робот

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

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

Ответ 1

Нет API для получения сеанса по идентификатору.

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

Ответ 2

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

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

request.getSession();

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

Ответ 3

В спецификации сервлета нет способа, но вы можете попробовать:

  • ручная настройка файла cookie в запросе Flash.

  • или делать то, что Тейлор L просто предложил, когда я вводил и добавлял параметр jsessionid путь к URI.

Оба метода привязывают ваше приложение к запуску в контейнере сервлетов, который ведет себя как Tomcat; Я думаю, что большинство из них это делает. Оба также потребуют, чтобы ваш Flash-апплет запрашивал у страницы свои файлы cookie, что может налагать зависимость от JavaScript.

Ответ 4

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

Итак, как насчет этого для гораздо более простого решения. Я реализовал это, и он работает очень хорошо. Таким образом, на странице, загружающей объект загрузки 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);

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

Ответ 5

Если вы используете 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, и он должен работать.

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