2012-02-15 61 views
2

這是我的使用案例。Seam 3如何在登錄後處理「重定向捕獲視圖」功能?

我有一個登錄頁面,它是/public/login.xhtml。我的所有其他頁面在到達之前都需要登錄。他們在/pages/目錄中。

我想的是:

  1. 如果我到http://host/myapp/pages/*用戶訪問它首先他重定向到登錄頁面,然後,到了URL,他首先進入。
  2. 如果我的用戶訪問http://host/myapp/,它會首先將其重定向到登錄頁面,然後再重定向到/pages/home.xhtml
  3. 如果我的用戶訪問http://host/myapp/public/login.xhtml,它會首先將其重定向到登錄頁面,然後再重定向到/pages/home.xhtml
  4. 如果我到http://host/myapp/public/login.xhtml用戶訪問,並已登錄,它重定向到/pages/home.xhtml

什麼是目前的工作?

有縫3(v3.1.0.Final)和安全+面孔模塊,我的使用情況N°1是自動工作有:

@ViewConfig 
public interface PagesConfig { 
    static enum Pages { 
     @ViewPattern("/pages/*") 
     @LoginView("/public/login.xhtml") 
     @LoggedIn 
     LOGGED_IN_PAGES, 
    } 
} 

我的問題是我不瞭解Seam如何將重定向到「捕獲視圖」

使用Seam 2,這是很容易理解,在components.xml我們有

<event type="org.jboss.seam.security.notLoggedIn"> 
    <action execute="#{redirect.captureCurrentView}" /> 
</event> 
<event type="org.jboss.seam.security.loginSuccessful"> 
    <action execute="#{redirect.returnToCapturedView}" /> 
</event> 

所以我們捕獲的事件notLoggedInloginSuccessful來處理與redirect組件。

在接縫3,我沒有發現配置:似乎沒有任何@Observes LoggedInEvent,並沒有Redirect類...

點n°2已與/index.htm文件來實現的:

<html><head> 
    <meta http-equiv="Refresh" content="0; URL=pages/home.xhtml"> 
</head></html> 

但是對於我的點n°3,我已經嘗試過不能完全工作的解決方案。

首先我想在login.xhtml

<f:metadata> 
    <s:viewAction action="#{loginAction.redirectToHome}" if="#{identity.loggedIn}" immediate="true" /> 
</f:metadata> 

及有無onPostback="true",我登錄後,我仍然在與該錯誤信息的登錄頁面(兩次):「無法找到匹配導航的情況下從-view-id的«/public/login.xhtml»行動«#{} identity.login»與預後«成功»。」。只有當我重新訪問http://host/myapp/public/login.xhtml時,我的viewAction纔會將我重定向到家中。

我也試過了導航規則faces-config.xml

<navigation-rule> 
    <from-view-id>/public/login.xhtml</from-view-id> 

    <navigation-case> 
     <if>#{identity.loggedIn}</if> 
     <to-view-id>/pages/home.xhtml</to-view-id> 
     <redirect /> 
    </navigation-case> 
</navigation-rule> 

但後來,我用例N°1被禁用:每次我登錄時,我被重定向到家裏。

最後,對於我的點n°4s:viewAction完成這項工作。


所以不會有人知道,以正確處理這4個用例(我想這是常見的用例)的最佳實踐,特別是點N°3?

回答

0

最後這裏是我做的。

<f:metadata> 
    <s:viewAction action="#{loginAction.redirectToHome}" immediate="true" /> 
</f:metadata> 

所以我爲了叫我redirectToHome方法,它重定向到 的/pages/home.xhtml刪除if="#{identity.loggedIn}"

  • 如果用戶已經通過身份驗證,那麼他將被重定向到主頁。
  • 如果他不是,那麼它會被重定向到主頁,會被重定向他登錄頁面感謝我@ViewConfig

這裏是loginAction

public void redirectToHome() throws IOException { 
    externalContext.redirect(externalContext.encodeActionURL(externalContext.getRequestContextPath()+"/pages/home.xhtml")); 
} 

我面臨的問題那時是我退出的時候。

這裏是我的註銷操作:

<h:commandLink action="/public/login" actionListener="#{securityAction.logout()}" value="Disconnect" immediate="true" /> 

而且securityAction.logout()方法:

public void logout() { 
    identity.logout(); 
    if (!conversation.isTransient()) { 
     conversation.end(); 
    } 
} 

的問題是,我被重定向到登錄頁面(感謝@ViewConfig我認爲) ,,但沒有PreLoginEvent被拋出,所以Seam LoginListener.observePreLoginEvent沒有被調用,所以我以前的URL沒有被放入會話中。所以,當我登錄(註銷後立刻),我被卡在登錄頁面上,但在已登錄

感謝Brian Leathemhe's previous answer,這裏是我做過什麼:在我的我的BaseAuthenticatorauthenticate方法,我稱之爲認證之後方法:

private void overrideRedirectToLogin() { 
    final String PRE_LOGIN_URL = LoginListener.class.getName() + "_PRE_LOGIN_URL"; 
    final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); 
    final Map<String, Object> sessionMap = externalContext.getSessionMap(); 
    String redirectURL = (String) sessionMap.get(PRE_LOGIN_URL); 

    if (redirectURL == null) { 
     final HttpServletRequest request = (HttpServletRequest) externalContext.getRequest(); 
     redirectURL = request.getRequestURL().toString(); 
    } 

    sessionMap.put(PRE_LOGIN_URL, redirectURL.replace("/public/login.xhtml", "/pages/home.xhtml")); 
} 

憑藉該解決方案,我以前的URL沒有在會議上確定,但至少,我的用戶會被重定向到主頁。

1

用例號 - 1 SeamFaces將最初請求的viewId存儲在用戶Session中,然後在成功登錄後重新路由到該視圖。它通過攔截來自Seam Security登錄按鈕的導航和fires a PostLoginEvent以及存儲在SessionMap中的數據來完成。

用例2 - 重定向的好方案!你也可以用@UrlMapping in your ViewConfig來做到這一點。

用例3 - 您的viewAction解決方案應該可以工作,但我相信您會遇到SEAMFACES-179。有一對夫婦的解決方案,你可以使用:

1)在你的登錄方法,你可以操縱由接縫面孔存儲SEESION地圖,這表現在這gist - )的Cody Lerum(將此溶液禮貌

2)使用PrettyFaces攔截的登錄查看請求,並rediret你,如果你還沒有登錄。

+0

感謝您的回覆,我試圖實現您的1)解決方案,但要做到這一點,我必須禁用Seam的LoginListener以使用我的...並且我無法做到這一點: (這是我現在面臨的:http://stackoverflow.com/questions/9332311/how-to-use-alternative-extending-a-concrete-class-in-a-webapp – 2012-02-20 13:13:48

+1

@AnthonyO。我想你誤解了解決方案1)。沒有必要替換LoginListener。相反,在執行登錄邏輯的\ @Secures方法中,您可以操縱Seam Faces哈希映射。放心,這是一個解決方法,而不是*應該如何工作。 – 2012-02-20 15:08:39