Сессия Java Spring не сохраняется между запросами

у меня есть этот контроллер

@Controller
@RequestMapping(value = "/login")
public class Login{

    @RequestMapping
    public ModelAndView mainPage(HttpServletRequest request){

        request.getSession().setAttribute("testSession", "Session test");

        return new ModelAndView("/login");

    }

    @RequestMapping(value = "/check")
    public View check(HttpServletRequest request){

        System.out.println(request.getSession(false)); //null

        return new RedirectView("/login");

    }

}

При доступе /login создаю сессию и добавляю в нее атрибут "testSession": request.getSession().setAttribute("testSession", "Session test");

На странице /login есть это <form action = "/login/check" method = "post">.

В /login/check я пытаюсь создать сессию в /login, но она пуста.

Почему сеанс не сохраняется между запросами?

P.S.: Мое приложение работает на удаленном сервере с Tomcat и Apache в качестве обратного прокси-сервера, и я получаю доступ к своему приложению через https://mydom.com

ОБНОВИТЬ

Я создал контроллер для тестовой сессии:

@Controller
@RequestMapping(value = "/sess")
public class TestSession{

    @RequestMapping(method = RequestMethod.GET)
    public void mainPage(HttpServletRequest request, HttpServletResponse response) throws IOException{

        //get or create session
        HttpSession session = request.getSession();

        response.setContentType("text/html");
        response.getWriter().println(session.getId());

    }

}

При каждом запросе к /sess печатается другой идентификатор.

Как вы это тестируете? Убедитесь, что вы отправляете идентификатор сеанса от клиента обратно на сервер.

M. Deinum 18.06.2019 15:14

@ М.Дейнум Как именно? Я новичок в Spring/Web

KunLun 18.06.2019 15:16

Это не имеет ничего общего с Spring, но все с тем, как вы это тестируете. Если вы не отправляете файл cookie sessionId (при условии, что вы используете файлы cookie), то восстанавливать нечего. Также убедитесь, что вы правильно настроили Spring Session.

M. Deinum 18.06.2019 15:17

@M.Deinum, мы можем поговорить здесь чат.stackoverflow.com/rooms/195135/… ? Я чувствую, что мне не хватает информации.

KunLun 18.06.2019 15:30

Просто объясните (или покажите), как вы это тестируете. Вы обсуждаете страницы, какие страницы, показывайте, как у вас дела. Также добавьте конфигурацию Spring Session (должен быть настроен фильтр).

M. Deinum 18.06.2019 15:31

Страница входа содержит форму с действием /login/check. /login/check - проверить сеанс и перенаправить обратно на страницу входа. У меня нет Spring Session configuration.

KunLun 18.06.2019 15:39

@KunLun, вы устанавливаете атрибут testSession и отправляете его на страницу /login. Что такое логин? Это JSP? Если да, проверьте, можете ли вы прочитать этот атрибут в JSP. Вы можете найти пример здесь beginnersbook.com/2013/11/…. Теперь, я думаю, проблема в том, что со страницы /login вы не отправляете этот атрибут методу, который обрабатывает конечную точку /check. Поэтому вам, вероятно, потребуется снова установить этот атрибут в /login JSP. И тогда вы сможете прочитать его в методе, который обрабатывает конечную точку /check.

Faraz 19.06.2019 11:05

@FarazDurrani Да, login — это JSP, и я могу прочитать testSession на login странице. Конечно, я не отправляю testSession в check. Идея сеанса состоит в том, чтобы хранить данные, связанные с пользователем, которые сохраняются до закрытия браузера, и не отправлять эти данные между запросами.

KunLun 19.06.2019 11:53

Куньлунь, тебе, возможно, придется освежить свои знания. Если вы не хотите вручную отправлять данные между запросами, рассмотрите возможность использования Spring Security.

Faraz 19.06.2019 14:54

@kunlun, найдите @SessionAttribute и посмотрите, решит ли это проблему без использования Spring Security.

Faraz 19.06.2019 15:02

Как вы называете метод check? Поскольку RequestMethod не указано, он использует значение по умолчанию (GET). Используете ли вы редирект со стороны клиента? Это может создать новый сеанс. Более того, как сказал @M.Deinum, проверьте, передаете ли вы идентификатор сеанса. Как? Проверьте, есть ли в URL-адресе что-то вроде JSESSIONID=XXXXXX или есть ли у вас файл cookie с идентификатором сеанса. Вы можете проверить весь сетевой трафик, используя инструменты разработчика в Google Chrome.

Angelo Immediata 20.06.2019 19:49

@AngeloImmediata Я звоню check из login.jsp с <form action = "/login/check">. У меня есть cookie JSESSIONID, но его значение меняется после каждого запроса. Даже если я обновлю страницу входа

KunLun 20.06.2019 21:33

Попробуйте отправить вместо получения

Angelo Immediata 20.06.2019 21:36

Давайте действовать по шагам. Вы тестируете, запуская свое приложение на своем ноутбуке, минуя веб-сервер (например, apache, ngnix или другой)? если нет... можете ли вы протестировать приложение на своем ноутбуке и проверить, работает ли оно так же?

Angelo Immediata 21.06.2019 15:00

Обычно я тестирую его прямо на сервере. Но теперь я протестировал /sess на локальном компьютере, и сеанс сохраняется. Значит проблема не в приложении? Это может быть от Tomcat/Apache?

KunLun 21.06.2019 15:13

Если сеанс сохраняется, мы можем предположить, что проблема не связана с приложением. Вы используете один сервер или кластер? Ваш apache настроен в режиме липкой сессии? Есть ли другой брандмауэр или что-то еще, что может фильтровать запросы?

Angelo Immediata 21.06.2019 15:26

Один сервер. Единственное, что я настроил на Apache, это 2 виртуальных хоста. Первый <VirtualHost *:80>(http), который постоянно перенаправляет на https(port 443). Другой <VirtualHost *:443>(https), где включите SSLCertificate и установите обратный прокси следующим образом: ProxyRequests off, ProxyPreserveHost on, ProxyPass / http://127.0.0.1:8080/myapp/ и ProxyPassReverse / http://127.0.0.1:8080/myapp/. Я не знаю, есть ли запрос брандмауэра или фильтра.

KunLun 21.06.2019 15:47

Давайте продолжить обсуждение в чате.

Angelo Immediata 21.06.2019 15:49

@AngeloImmediata Я решил. Прочитай мой ответ. И действительно спасибо за вашу помощь.

KunLun 21.06.2019 22:10
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
19
1 951
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы используете весеннюю безопасность? Может быть, вы можете установить http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) если вы сами управляете сессиями

Ссылка: https://www.baeldung.com/spring-security-session

Я не использую весеннюю безопасность

KunLun 18.06.2019 13:49

Это влияет только на то, как Spring Security обрабатывает сеансы, а НЕ на то, как его обрабатывает остальная часть вашего приложения.

M. Deinum 18.06.2019 15:15
Ответ принят как подходящий

Настоящая проблема была в пути JSessionID.

Путь JSessionID был /myapp. Это был результат Tomcat, потому что мое приложение обычно работает под mydom.com:8080/myapp

Но с Apache в качестве обратного прокси-сервера я запускаю свое приложение напрямую из mydom.com/, что делает JSessionID недействительным, потому что я не на mydom.com/myapp.

Поэтому я добавил новую строку в виртуальный хост от Apache (где установлен обратный прокси), чтобы изменить путь к файлам cookie:

ProxyPassReverseCookiePath /myapp /

Это мой последний VirtualHost, и теперь сессия сохраняется между запросами.

<VirtualHost *:80>

    ServerName mydom.com

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/myapp/
    ProxyPassReverse / http://127.0.0.1:8080/myapp/
    ProxyPassReverseCookiePath /myapp /

</VirtualHost>

Если кто-то считает, что в этом ответе отсутствует/неверная информация, оставьте комментарий с подробностями, чтобы обновить ответ.

KunLun 21.06.2019 22:07

Другие вопросы по теме