2011-11-06 66 views
3

我試圖用JSF 2.0來以一種整潔的方式實現登錄/記住我/註銷管理。由於傳統的<form action="j_security_check" ...方式缺乏靈活性,我決定採用不同的方式,但是我發現了一個問題。用戶使用JSF 2.0登錄

通過<security-domain>和web.xml中的<security-constraint>,<login-config><form-login-page>在申請服務器中正確設置聲明性安全。

登錄頁面:

<h:form id="loginForm"> 
    <h:panelGrid columns="2" cellspacing="5"> 
     <h:outputText value="Username" /> 
     <h:inputText value="#{loginBean.username}" /> 
     <h:outputText value="Password:" /> 
     <h:inputText value="#{loginBean.password}" /> 
     <h:outputLabel value=""/> 
     <h:commandButton value="Login" action="#{loginBean.login}" /> 
    </h:panelGrid>  
</h:form> 

和簡單LoginBean#登錄():

public String login() 
{ 
    HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();   
    try { 
     request.login(username, password); 
    } 
    catch (ServletException e) { 
     FacesContext.getCurrentInstance().addMessage("Unknown login... 
     return null; 
    }  
    return "i_dont_know_where_you_were_going"; 
} 

一切正常,但在成功登錄後,我不知道如何轉發用戶到其最初的要求。由於登錄頁面自動插入在客戶端請求和「任何」安全資源之間,因此我需要一種方法來了解將動作重定向到何處。 request.getRequestURL()沒有幫助,可能是因爲RequestDispatcher#forward()(它會覆蓋請求url)干預。你認爲這是管理登錄過程的適當方式嗎?如果是這樣,關於這個問題的任何暗示?

非常感謝!

回答

6

在您的登錄視圖中添加類似以下行的內容。它在登錄期間存儲請求的頁面。

<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" /> 

然後在您的登錄bean中獲取請求的uri。

FacesContext context = FacesContext.getCurrentInstance(); 
String redirect = context.getExternalContext().getRequestParameterMap().get("redirect"); 

?faces-redirect=true添加到字符串並返回它。

2

以上回答非常完美,只是指出,以粗心.. F:PARAM名稱應該是裏面的東西像命令按鈕...

<p:commandButton value="Entrar" icon="ui-icon-disk" action="#{userMB.login}" update="avisos,mensagens" ajax="false"> 
<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" /> 
</ p: commandButton> 
0

這似乎只是工作放在按鈕之間時( Mojarra 2.2,Glassfish 4)。您將需要這兩個<f:param標籤javax.servlet.forward.request_urijavax.servlet.forward.query_string以確保您準確地重定向回所有類型的URL(帶或不帶查詢字符串)。確保您的登錄頁面中包含類似以下代碼段的內容,即您在web.xml登錄 (<form-login-page>/login.xhtml</form-login-page>)中指定的頁面。

<h:commandButton value="Login" action="#{securityController.login()}"> 
    <f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" /> 
    <f:param name="query_string" value="#{requestScope['javax.servlet.forward.query_string']}" /> 
</h:commandButton> 

然後你可以檢索的支持Bean這兩個參數的形式提交後如下

public String login() { 
    try { 
     String nextPage = "/index.xhtml"; // have a default value in case the user goes to login page directly. 
     ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext(); 
     Map<String, String> map = ctx.getRequestParameterMap(); 
     String redirect = map.get("redirect"); 
     String queryString = map.get("query_string"); 
     HttpServletRequest request = (HttpServletRequest) ctx.getRequest(); 
     request.login(this.username, this.password); 
     // here login is successful otherwise it would've thrown exception 
     // now let's check the kind of URL our user was going to 
     if (redirect != null && !redirect.isEmpty()) { // if redirect is null, return the default page 
     // please use faces-redirect = true to ensure URL change in the browser 
      if (queryString != null) { 
       nextPage = redirect + "?" + queryString + "&faces-redirect=true"; 
      } else { // there is no query string, nextPage = redirect 
       nextPage = redirect + "&faces-redirect=true"; 
      } 
      // Caveat: You may not need the next lines of code. 
      // I discovered that the `redirect` string has my context path 
      // value in it and so it was'nt redirecting. Remove the context path 
      if (nextPage.contains(request.getContextPath())) { 
      nextPage = nextPage.substring(request.getContextPath().length()); 
      } 
     } 

    } catch (ServletException ex) { 
     Logger.getLogger(SecurityController.class.getName()).log(Level.SEVERE, null, ex); 
     // invalid username or password 
     return "/login.xhtml?failed=true"; // or login error page 
    } 
return nextPage; 
} 

我希望這可以幫助別人。