簡體   English   中英

登錄后重定向回頁面

[英]Redirect back to a page after a login

我正在用一系列Servlets做一個簡單的論壇,每個Servlets代表一個家,主題,發布,登錄和用戶列表頁面。 在其中一些頁面上,當用戶未登錄時會顯示一個鏈接。

我想要實現的是在登錄后觸發重定向(在RequestDispatcher上使用forward()),以便瀏覽器在單擊登錄鏈接之前返回用戶所在的頁面。 為了做到這一點,我看到兩個解決方案。

第一個解決方案是使用一個帶有登錄按鈕和不可見字段的HTML Form ,該字段將包含將要重定向為Parameter頁面的信息。 這是可行的,但我想嘗試其他的東西。

第二種解決方案是在session中添加一個Attribute ,以某種方式表示第一個“頁面”。 這可能包含一個String,但這與第一種方法沒有什么不同。 另一個轉折是添加對HttpServlet的引用並使用instanceof或靜態String變量,該變量可用於以某種方式標識Servlet。 但是,這需要為所有Servlets創建一個共同的祖先類。

或許有另一個簡單的解決方案,你可以看到,這將形成一個良好的妥協? 或者,上述解決方案中的一種可能完全可以接受?

我更喜歡第二個解決方案之上的第一個。 這是請求范圍的信息,實際上不屬於會話,它只會導致“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() ,但是我不這樣做,因為這是客戶端控制的並且沒有總是返回可靠的信息。 有些客戶已經禁用它或正在使用某些軟件,這些軟件使用無效值來欺騙它,例如大多數( 咳嗽 )賽門鐵克產品都會這樣做。

您的第一個建議的方法是最好的方法。 擁有一個帶有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

章:認證成功和失敗的應用流程

...如果身份驗證成功,生成的身份驗證對象將被放入SecurityContextHolder。 然后將調用配置的AuthenticationSuccessHandler以將用戶重定向或轉發到適當的目標。 默認情況下,使用SavedRequestAwareAuthenticationSuccessHandler,這意味着在要求用戶登錄之前,用戶將被重定向到他們請求的原始目標。 ...

使用表單中的隱藏字段非常標准。 為什么嘗試重新發明輪子?

好的,這就是我所做的。 登錄是一個兩步過程,一個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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM