开发者

Redirect back to a page after a login

I'm doing a simple forum with a series of Servlets that each represent a home, topic, postedit, login and userlist page. On some of these pages there is a link that appears when a user isn't logged in.

What I'd like to achieve is to trigger a redirection (using forward() on a RequestDispatcher) a开发者_JAVA技巧fter a login so the browser goes back to the page where a user was before clicking the login link. In order to do this, I see two solutions.

The first solution is to have an HTML Form with a login button and an invisible field that will contain information that will say what page to redirect as a Parameter. This is doable but I'd like to try something else.

The second solution is to add an Attribute to the session that represents the first "page" in some way. This could contain a String but this is no different from the first approach. Another twist would be to add a reference to the HttpServlet and to use instanceof or a static String variable that could be used to identify the Servlet in some way. However, this would require creating a common ancestor class for all the Servlets.

Perhaps there is another simple solution that you can see that would form a good compromise ? Or, maybe one of the above solutions is perfectly acceptable ?


I would prefer the first above the second solution. This is request scoped information and really doesn't belong in the session, it would only lead to "wtf?" experiences when you have multiple windows/tabs open in the same session.

On the link to the login page, just pass the current URL as request parameter:

<a href="/login?from=${pageContext.request.requestURI}">Login</a>

Or if it is a POST form to the login page:

<input type="hidden" name="from" value="${pageContext.request.requestURI}">

In the login form, transfer it to the next request as hidden variable:

<input type="hidden" name="from" value="${param.from}">

In the login servlet, make use of it:

User user = userDAO.find(username, password);
if (user != null) {
    request.getSession().setAttribute("user", user);
    response.sendRedirect(request.getParameter("from"));
} else {
    // Show error.
}

Fairly simple, isn't it? :)

Some may suggest to use request.getHeader("referer") for this inside the login form instead of request.getRequestURI() in the link/button before login, but I wouldn't do that as this is client-controlled and doesn't always return reliable information. Some clients have disabled it or are using some software which spoofes it with an invalid value, such as most of the (cough) Symantec products do.


Your first suggested approach is the best one. Have a hidden field with value=request.getRequestURI() and redirect to that URI after login.

Using refererwon't work, because IE (at least some of its versions) doesn't set the referer header.

Storing a parameter in the session would cause strange behaviour if the user opens multiple tabs.

Edit: To illustrate the question better:

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

Most answers assume that a "login" link/button is clicked, and then the login page is opened. This is only one side of the story. In that case the original resource URL can be added as a parameter, and placed in the login form (in a hidden field).

But in case of forwarding from a protected resource to the login page, the hidden field should contain the immediate request URL.

This, of course, isn't what's in the question, but will eventually arise as a situation and should be considered as well.


If you want to do this with pages, your login page could look at the referer (sic) header in the request that loaded it (request.getHeader("referer")) to see if that's a page on your site (if not -- or if the header is missing -- use a default of some kind). Then it would store that URL (I'd probably use a hidden field, as you said, in the login form; but a session var would work too). When the login is complete, issue a redirect to the stored URL.

These days, I'd probably use all of that as a fallback mechanism if I couldn't do the login by overlaying a dialog on the page and logging in via Ajax -- and so, never leaving the page at all.


Edit Or better yet, as Bozho points out, encode the target page into your link to the login page. Although it's not true that IE doesn't set the "referer" header (it does), referer is not required and can be disabled, and since you're already dynamically creating the page linking to the login form, why be vulnerable to that if you don't need to be.


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

chapter: Application Flow on Authentication Success and Failure

... If authentication is successful, the resulting Authentication object will be placed into the SecurityContextHolder. The configured AuthenticationSuccessHandler will then be called to either redirect or forward the user to the approprate destination. By default a SavedRequestAwareAuthenticationSuccessHandler is used, which means that the user will be redirected to the original destination they requested before they were asked to login. ...


Using the hidden field in the form is pretty standard. Why try reinventing the wheel?


Ok, here's what I've done. Login is a two-step process with one Servlet showing a a form and another controlling if the username+password combination is correct. The two could be combined.

A parameter can be sent through a form or through a link (JSP hasn't been added yet):

out.println( "Login <a href='LoginServlet?comeback=home'>here</a><br>" );  

The parameter is then retrieved as follows:

String comeback = request.getParameter("comeback");

Once the login information has been checked, redirection can be done as follows:

RequestDispatcher rd = request.getRequestDispatcher( redirectionPath );

if( rd != null )
   rd.forward(request, response);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜