Перенаправить обратно на страницу после входа в систему - PullRequest
13 голосов
/ 17 декабря 2009

Я делаю простой форум с серией Servlets, каждый из которых представляет домашнюю страницу, тему, postsit, страницу входа и страницу пользователя. На некоторых из этих страниц есть ссылка, которая появляется, когда пользователь не вошел в систему.

Чего я хотел бы добиться, так это инициировать перенаправление (используя forward () для RequestDispatcher) после входа в систему, чтобы браузер возвращался на страницу, где находился пользователь, прежде чем щелкнуть ссылку входа в систему. Для этого я вижу два решения.

Первое решение состоит в том, чтобы иметь HTML Form с кнопкой входа в систему и невидимым полем, которое будет содержать информацию, которая скажет, какую страницу перенаправить как Parameter. Это выполнимо, но я бы хотел попробовать что-то еще.

Второе решение - добавить Attribute к session, который каким-то образом представляет первую «страницу». Это может содержать строку, но это ничем не отличается от первого подхода. Другим поворотом было бы добавить ссылку на HttpServlet и использовать instanceof или статическую переменную String, которая могла бы использоваться для идентификации сервлета каким-либо образом. Однако для этого потребуется создать общий класс предков для всех Servlets.

Возможно, есть еще одно простое решение, которое, как вы видите, могло бы стать хорошим компромиссом? Или, может быть, одно из приведенных выше решений вполне приемлемо?

Ответы [ 6 ]

24 голосов
/ 17 декабря 2009

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

4 голосов
/ 17 декабря 2009

Ваш первый предложенный подход - лучший. Иметь скрытое поле с value=request.getRequestURI() и перенаправлять на этот URI после входа в систему.

Использование referer не будет работать, потому что IE (по крайней мере, некоторые из его версий) не устанавливает заголовок referer.

Хранение параметра в сеансе может вызвать странное поведение, если пользователь открывает несколько вкладок.

Edit: Чтобы лучше проиллюстрировать вопрос:

some resource -> (requests protected resource) -> (gets forwarded to the login page) -> (should be redirected to the original resource)

В большинстве ответов предполагается, что нажата ссылка / кнопка «Войти», после чего открывается страница входа. Это только одна сторона истории. В этом случае исходный URL ресурса может быть добавлен в качестве параметра и помещен в форму входа в систему (в скрытом поле).

Но в случае пересылки с защищенного ресурса на страницу входа в систему скрытое поле должно содержать URL-адрес немедленного запроса.

Это, конечно, не то, что находится в вопросе, но в конечном итоге возникнет как ситуация, и ее также следует учитывать.

3 голосов
/ 17 декабря 2009

Если вы хотите сделать это со страницами, ваша страница входа может посмотреть на заголовок referer (sic) в запросе, который его загрузил (request.getHeader("referer")), чтобы увидеть, является ли это страницей на вашем сайте (если нет - или если заголовок отсутствует - используйте какой-либо тип по умолчанию). Затем он будет хранить этот URL (я бы, вероятно, использовал скрытое поле, как вы сказали, в форме входа в систему; но сессия var тоже подойдет). После завершения входа в систему выполните перенаправление на сохраненный URL-адрес.

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


Редактировать Или еще лучше, как указывает Божо, закодировать целевую страницу в свою ссылку на страницу входа. Хотя не верно, что IE не устанавливает заголовок "referer" (он делает), referer не требуется и может быть отключен, и поскольку вы уже динамически создаете страницу, ссылающуюся на форму входа зачем быть уязвимым к этому, если вам это не нужно.

1 голос
/ 17 декабря 2009

Использование скрытого поля в форме довольно стандартно. Зачем пытаться изобретать велосипед?

1 голос
/ 17 декабря 2009

из: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.pdf

глава: Поток приложений при успешной и неудачной аутентификации

... Если аутентификация прошла успешно, результирующий объект аутентификации будет помещен в SecurityContextHolder. Затем будет вызван настроенный AuthenticationSuccessHandler, чтобы либо перенаправить, либо перенаправить пользователя в соответствующий пункт назначения. По умолчанию используется SavedRequestAwareAuthenticationSuccessHandler, что означает, что пользователь будет перенаправлен в исходное место назначения, которое он запрашивал, прежде чем его попросили войти в систему. ...

0 голосов
/ 23 декабря 2009

Хорошо, вот что я сделал. Вход в систему представляет собой двухэтапный процесс: один сервлет показывает форму, а другой контролирует правильность комбинации имени пользователя и пароля. Два могут быть объединены.

Параметр может быть отправлен через форму или по ссылке (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);
...