登录后重定向回页面

时间:2009-12-17 11:50:56

标签: java servlets redirect

我正在使用一系列Servlets做一个简单的论坛,每个论坛代表一个主页,主题,发布,登录和用户列表页面。在其中一些页面上,当用户未登录时会显示一个链接。

我想要实现的是在登录后触发重定向(在RequestDispatcher上使用forward()),以便浏览器在单击登录链接之前返回用户所在的页面。为了做到这一点,我看到了两个解决方案。

第一个解决方案是让HTML Form具有登录按钮和不可见字段,该字段将包含将要重定向到Parameter的页面的信息。这是可行的,但我想尝试其他的东西。

第二个解决方案是以Attributesession添加代表第一个“页面”的Servlets。这可能包含一个String,但这与第一种方法没有什么不同。另一个转折是添加对HttpServlet的引用并使用instanceof或静态String变量,该变量可用于以某种方式标识Servlet。但是,这需要为所有{{1}}创建一个共同的祖先类。

也许有另一个简单的解决方案,你可以看到,这将形成一个良好的妥协?或者,上述解决方案中的一种可能是完全可以接受的吗?

6 个答案:

答案 0 :(得分:24)

我更喜欢第一个高于第二个解决方案。这是请求作用域信息,并且实际上不属于会话,它只会导致“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}">

在登录servlet中,使用它:

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(),但我不会这样做,因为这是客户端控制的并且不会总是返回可靠的信息。有些客户已禁用它或正在使用某些软件,这些软件使用无效值来欺骗它,例如大多数( cough )赛门铁克产品。

答案 1 :(得分:4)

您首先建议的方法是最好的方法。拥有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。

当然,这不是问题中的问题,但最终会出现这种情况,也应予以考虑。

答案 2 :(得分:3)

如果您想对页面执行此操作,您的登录页面可以查看加载它(request.getHeader("referer"))的请求中的referer(sic)标题,以查看您的网站上是否有页面(如果不是 - - 或者如果标题丢失 - 使用某种默认值)。然后它会存储该URL(我可能会使用隐藏字段,如您所说,在登录表单中;但会话var也可以使用)。登录完成后,发出重定向到存储的URL。

现在,如果我无法通过在页面上覆盖对话框并通过Ajax登录来进行登录,我可能会将所有这些用作后备机制 - 因此,永远不要离开页面。


编辑或者更好的是,正如Bozho指出的那样,将目标网页编码为您登录页面的链接。虽然是的,IE没有设置“referer”标题(确实如此),但不需要referer并且可以禁用它,因为你已经动态创建了链接到登录的页面形式,如果你不需要,为什么容易受到影响。

答案 3 :(得分:1)

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

章:认证成功和失败的应用程序流程

... 如果身份验证成功,则生成的身份验证对象将放入SecurityContextHolder。然后将调用配置的AuthenticationSuccessHandler以将用户重定向或转发到适当的目标。默认情况下,使用SavedRequestAwareAuthenticationSuccessHandler,这意味着在要求用户登录之前,用户将被重定向到他们请求的原始目标。 ...

答案 4 :(得分:1)

使用表单中的隐藏字段非常标准。为什么尝试重新发明轮子?

答案 5 :(得分:0)

好的,这就是我所做的。登录是一个两步过程,一个Servlet显示一个表单,另一个控制用户名+密码组合是否正确。这两者可以合并。

参数可以通过表单或链接发送(尚未添加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);
相关问题