у меня есть этот контроллер
@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 печатается другой идентификатор.
@ М.Дейнум Как именно? Я новичок в Spring/Web
Это не имеет ничего общего с Spring, но все с тем, как вы это тестируете. Если вы не отправляете файл cookie sessionId (при условии, что вы используете файлы cookie), то восстанавливать нечего. Также убедитесь, что вы правильно настроили Spring Session.
@M.Deinum, мы можем поговорить здесь чат.stackoverflow.com/rooms/195135/… ? Я чувствую, что мне не хватает информации.
Просто объясните (или покажите), как вы это тестируете. Вы обсуждаете страницы, какие страницы, показывайте, как у вас дела. Также добавьте конфигурацию Spring Session (должен быть настроен фильтр).
Страница входа содержит форму с действием /login/check. /login/check - проверить сеанс и перенаправить обратно на страницу входа. У меня нет Spring Session configuration.
@KunLun, вы устанавливаете атрибут testSession и отправляете его на страницу /login. Что такое логин? Это JSP? Если да, проверьте, можете ли вы прочитать этот атрибут в JSP. Вы можете найти пример здесь beginnersbook.com/2013/11/…. Теперь, я думаю, проблема в том, что со страницы /login вы не отправляете этот атрибут методу, который обрабатывает конечную точку /check. Поэтому вам, вероятно, потребуется снова установить этот атрибут в /login JSP. И тогда вы сможете прочитать его в методе, который обрабатывает конечную точку /check.
@FarazDurrani Да, login — это JSP, и я могу прочитать testSession на login странице. Конечно, я не отправляю testSession в check. Идея сеанса состоит в том, чтобы хранить данные, связанные с пользователем, которые сохраняются до закрытия браузера, и не отправлять эти данные между запросами.
Куньлунь, тебе, возможно, придется освежить свои знания. Если вы не хотите вручную отправлять данные между запросами, рассмотрите возможность использования Spring Security.
@kunlun, найдите @SessionAttribute и посмотрите, решит ли это проблему без использования Spring Security.
Как вы называете метод check? Поскольку RequestMethod не указано, он использует значение по умолчанию (GET). Используете ли вы редирект со стороны клиента? Это может создать новый сеанс. Более того, как сказал @M.Deinum, проверьте, передаете ли вы идентификатор сеанса. Как? Проверьте, есть ли в URL-адресе что-то вроде JSESSIONID=XXXXXX или есть ли у вас файл cookie с идентификатором сеанса. Вы можете проверить весь сетевой трафик, используя инструменты разработчика в Google Chrome.
@AngeloImmediata Я звоню check из login.jsp с <form action = "/login/check">. У меня есть cookie JSESSIONID, но его значение меняется после каждого запроса. Даже если я обновлю страницу входа
Попробуйте отправить вместо получения
Давайте действовать по шагам. Вы тестируете, запуская свое приложение на своем ноутбуке, минуя веб-сервер (например, apache, ngnix или другой)? если нет... можете ли вы протестировать приложение на своем ноутбуке и проверить, работает ли оно так же?
Обычно я тестирую его прямо на сервере. Но теперь я протестировал /sess на локальном компьютере, и сеанс сохраняется. Значит проблема не в приложении? Это может быть от Tomcat/Apache?
Если сеанс сохраняется, мы можем предположить, что проблема не связана с приложением. Вы используете один сервер или кластер? Ваш apache настроен в режиме липкой сессии? Есть ли другой брандмауэр или что-то еще, что может фильтровать запросы?
Один сервер. Единственное, что я настроил на 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/. Я не знаю, есть ли запрос брандмауэра или фильтра.
Давайте продолжить обсуждение в чате.
@AngeloImmediata Я решил. Прочитай мой ответ. И действительно спасибо за вашу помощь.




Вы используете весеннюю безопасность? Может быть, вы можете установить
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) если вы сами управляете сессиями
Ссылка: https://www.baeldung.com/spring-security-session
Я не использую весеннюю безопасность
Это влияет только на то, как Spring Security обрабатывает сеансы, а НЕ на то, как его обрабатывает остальная часть вашего приложения.
Настоящая проблема была в пути 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>
Если кто-то считает, что в этом ответе отсутствует/неверная информация, оставьте комментарий с подробностями, чтобы обновить ответ.
Как вы это тестируете? Убедитесь, что вы отправляете идентификатор сеанса от клиента обратно на сервер.