2011-11-06 5 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']}" /> 

그런 다음 요청한 uri를 로그인 빈에서 가져옵니다.

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

문자열에 ?faces-redirect=true을 추가하여 반환하십시오. 매개 변수 이름이있는 명령과 같은 내부해야 ... 버튼 사이에 위치 할 때

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

는 위의 대답은 단지 부주의 .. F에 지적, 완벽하게 작동 Mojarra 2.2, Glassfish 4). 이 두 개의 <f:param 태그 javax.servlet.forward.request_urijavax.servlet.forward.query_string이 있어야 모든 유형의 URL (쿼리 문자열 유무에 관계없이)로 정확하게 리디렉션 될 수 있습니다. 로그인 페이지, 즉 로그인 (<form-login-page>/login.xhtml</form-login-page>)에 대해 web.xml에 지정한 페이지 아래에있는 스 니펫과 유사해야합니다.

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

그런 다음 나는이 사람을 도움이되기를 바랍니다

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

다음과 같이 양식 제출 후 백업 빈의 두 매개 변수를 검색 할 수 있습니다.

0

이 만 작동하는 것 같다 (:

관련 문제