Перенаправление на страницу после входа в систему
Я делаю простой форум с серией Servlets
, каждый из которых представляет домашнюю страницу, тему, посылку, страницу входа и списка пользователей. На некоторых из этих страниц есть ссылка, которая появляется, когда пользователь не вошел в систему.
То, что я хотел бы достичь, - вызвать перенаправление (используя forward() на RequestDispatcher) после входа в систему, чтобы браузер вернулся к странице, на которой был пользователь, прежде чем щелкнуть ссылку для входа. Для этого я вижу два решения.
Первое решение - иметь HTML Form
с кнопкой входа и невидимым полем, которое будет содержать информацию, которая скажет, какую страницу перенаправить как Parameter
. Это выполнимо, но я хотел бы попробовать что-то еще.
Второе решение - добавить Attribute
в session
, который каким-то образом представляет первую "страницу". Это может содержать строку, но это ничем не отличается от первого подхода. Другим поворотным моментом было бы добавить ссылку на HttpServlet и использовать instanceof или статическую переменную String, которая может быть использована для идентификации сервлета каким-то образом. Однако для этого потребуется создать общий класс предков для всех Servlets
.
Возможно, есть еще одно простое решение, которое вы можете увидеть, что будет хорошим компромиссом? Или, может быть, одно из вышеуказанных решений вполне приемлемо?
Ответы
Ответ 1
Я предпочел бы первое выше второго решения. Это запрос с ограниченной информацией и действительно не относится к сеансу, это приведет только к "wtf?". когда у вас открыто несколько окон/вкладок в одном сеансе.
В ссылке на страницу входа просто укажите текущий URL-адрес в качестве параметра запроса:
<a href="/login?from=${pageContext.request.requestURI}">Login</a>
Или, если это форма POST на странице входа в систему:
<input type="hidden" name="from" value="${pageContext.request.requestURI}">
В форме входа передайте его следующему запросу в виде скрытой переменной:
<input type="hidden" name="from" value="${param.from}">
В сервлете входа используйте его:
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect(request.getParameter("from"));
} else {
// Show error.
}
Довольно просто, не так ли?:)
Некоторые могут предложить использовать request.getHeader("referer")
для этого внутри формы входа вместо request.getRequestURI()
в ссылке/до входа в систему, но я бы этого не сделал, поскольку это контролируется клиентом и не всегда возвращает надежный Информация. Некоторые клиенты отключили его или используют какое-то программное обеспечение, которое подделывает его с недопустимым значением, например, большинство продуктов (кашля) Symantec.
Ответ 2
Ваш первый предложенный подход является лучшим. У вас есть скрытое поле с value=request.getRequestURI()
и перенаправление на этот URI после входа в систему.
Использование referer
не будет работать, потому что IE (по крайней мере, некоторые его версии) не устанавливает заголовок referer
.
Сохранение параметра в сеансе вызовет странное поведение, если пользователь откроет несколько вкладок.
Изменить:
Чтобы лучше проиллюстрировать вопрос:
some resource -> (requests protected resource) -> (gets forwarded to the login page) -> (should be redirected to the original resource)
В большинстве ответов предполагается, что нажата кнопка "Логин" /кнопка, а затем открывается страница входа в систему. Это только одна сторона истории. В этом случае исходный URL ресурса может быть добавлен в качестве параметра и помещен в форму входа (в скрытом поле).
Но в случае пересылки с защищенного ресурса на страницу входа в систему скрытое поле должно содержать URL-адрес прямого запроса.
Это, конечно, не то, что в этом вопросе, но в конечном итоге возникнет как ситуация и должно также рассматриваться.
Ответ 3
Если вы хотите сделать это со страницами, ваша страница входа в систему может посмотреть заголовок referer (sic) в запросе, который его загрузил (request.getHeader("referer")
), чтобы увидеть, была ли эта страница на вашем сайте (если нет - или если заголовок отсутствует - используйте по умолчанию какой-либо тип). Затем он сохранит этот URL (я бы, вероятно, использовал скрытое поле, как вы сказали, в форме входа, но также будет работать var var). Когда логин будет завершен, выполните перенаправление на сохраненный URL.
В наши дни я, вероятно, использовал бы все это в качестве резервного механизма, если бы не смог выполнить вход, наложив диалог на страницу и войдя в систему через Ajax - и, таким образом, никогда не покидая страницу вообще.
Изменить. Еще лучше, как указывает Божо, кодируйте целевую страницу в свою ссылку на страницу входа. Хотя это не так, что IE не устанавливает заголовок "referer" (он делает это), референт не требуется и может быть отключен, и поскольку вы уже динамически создаете страницу, ссылающуюся на форму входа, почему бы если вам не нужно быть.
Ответ 4
от:
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.pdf
глава: Поток приложений при успешном завершении и неудаче аутентификации
...
Если аутентификация прошла успешно, результирующий объект аутентификации будет помещен в SecurityContextHolder. Затем настроенный AuthenticationSuccessHandler будет вызван либо для перенаправления, либо для переадресации пользователя в назначенное место назначения. По умолчанию используется SavedRequestAwareAuthenticationSuccessHandler, что означает, что пользователь будет перенаправлен на исходное место назначения, которое они запросили, прежде чем им было предложено войти в систему.
...
Ответ 5
Использование скрытого поля в форме довольно стандартно. Зачем пытаться изобретать колесо?
Ответ 6
Хорошо, вот что я сделал. Вход - это двухэтапный процесс с одним сервлетом, показывающим форму, а другой - контроль правильности комбинации имени пользователя и пароля. Эти два могут быть объединены.
Параметр может быть отправлен через форму или по ссылке (JSP еще не добавлен):
out.println( "Login <a href='LoginServlet?comeback=home'>here</a><br>" );
Затем параметр извлекается следующим образом:
String comeback = request.getParameter("comeback");
Как только информация для входа в систему была проверена, перенаправление может быть выполнено следующим образом:
RequestDispatcher rd = request.getRequestDispatcher( redirectionPath );
if( rd != null )
rd.forward(request, response);