Java 登录后重定向回页面

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1921230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:27:10  来源:igfitidea点击:

Redirect back to a page after a login

javaservletsredirect

提问by James P.

I'm doing a simple forum with a series of Servletsthat 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.

我正在做一个简单的论坛,Servlets其中每个论坛都代表一个主页、主题、帖子编辑、登录和用户列表页面。在其中一些页面上,当用户未登录时会出现一个链接。

What I'd like to achieve is to trigger a redirection (using forward() on a RequestDispatcher) after 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.

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

The first solution is to have an HTML Formwith 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.

第一个解决方案是拥有一个Form带有登录按钮的 HTML和一个不可见的字段,该字段将包含说明将哪个页面重定向为Parameter. 这是可行的,但我想尝试其他方法。

The second solution is to add an Attributeto the sessionthat 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.

第二种解决方案是以某种方式Attributesession代表第一个“页面”的 中添加 。这可以包含一个字符串,但这与第一种方法没有什么不同。另一个变化是添加对 HttpServlet 的引用,并使用 instanceof 或静态字符串变量,这些变量可用于以某种方式识别 Servlet。但是,这需要为所有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 ?

也许您可以看到另一种简单的解决方案可以形成良好的妥协?或者,也许上述解决方案之一是完全可以接受的?

采纳答案by BalusC

I would prefer the first above the second solution. This is requestscoped 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.

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

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

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

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

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

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

<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:

在登录 servlet 中,使用它:

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.

有些人可能会建议request.getHeader("referer")在登录表单内而不是request.getRequestURI()在登录前的链接/按钮中使用它,但我不会这样做,因为这是客户端控制的并且并不总是返回可靠的信息。一些客户已禁用它或正在使用某些软件以无效值欺骗它,例如大多数()赛门铁克产品。

回答by T.J. Crowder

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.

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

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



EditOr better yet, as Bozho points out, encode the target page into your link to the login page. Although it's nottrue 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.

编辑或者更好的是,正如 Bozho 指出的那样,将目标页面编码到登录页面的链接中。尽管这不是真正的IE浏览器没有设置的“引荐”头(它),不需要引用者,并且可以禁用,因为你已经创建动态链接到登录表单的页面,为什么会受到这如果你不需要。

回答by nils petersohn

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

来自: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. ...

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

回答by Jeremy Raymond

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

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

回答by Bozho

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

您建议的第一种方法是最好的方法。有一个隐藏字段,value=request.getRequestURI()并在登录后重定向到该 URI。

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

使用referer将不起作用,因为 IE(至少它的某些版本)没有设置referer标头。

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)

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).

大多数答案假设单击“登录”链接/按钮,然后打开登录页面。这只是故事的一方面。在这种情况下,原始资源 URL 可以作为参数添加,并放置在登录表单中(在隐藏字段中)。

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

但是在从受保护资源转发到登录页面的情况下,隐藏字段应包含即时请求 URL。

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

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

回答by James P.

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.

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

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

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

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);