登录后重定向回页面

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

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

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

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

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

我更喜欢第一个高于第二个解决方案。 这是请求范围的信息,并且实际上不属于会话,它只会导致“wtf?” 在同一会话中打开多个窗口/选项卡时的体验。

在登录页面的链接上,只需将当前URL作为请求参数传递:

 Login 

或者,如果它是登录页面的POST表单:

  

在登录表单中,将其作为隐藏变量传输到下一个请求:

  

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

您的第一个建议的方法是最好的方法。 拥有一个带有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。

当然,这不是问题所在,但最终会出现这种情况,也应该加以考虑。

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

这些天,如果我不能通过覆盖页面上的对话框并通过Ajax登录来进行登录,我可能会将所有这些用作回退机制 – 所以,永远不要离开页面。


编辑或者更好的是,正如Bozho指出的那样,将目标页面编码为您登录页面的链接。 虽然IE不设置“referer”标题(确实如此) 并不是真的,但是不需要referer并且可以禁用referer,并且由于你已经动态创建链接到登录表单的页面,为什么容易受到攻击如果你不需要。

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

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

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

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

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

参数可以通过表单或链接发送(尚未添加JSP):

 out.println( "Login here
" );

然后检索该参数,如下所示:

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

检查登录信息后,可以按如下方式完成重定向:

 RequestDispatcher rd = request.getRequestDispatcher( redirectionPath ); if( rd != null ) rd.forward(request, response);