2011-11-06 68 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; 
} 

我希望这可以帮助别人。