2012-01-15 2 views
2

세션 리스너를 구현했습니다. 나는 사용자가 세션이 파괴 된 후에 사이트를 사용하려고 할 때 환영 페이지 (로그인 페이지)로 리디렉션되어야한다고 생각합니다. 나는 loging?faces-redirect=true을 수행하여 이것을 시도했지만 실제로 loginpage로 리디렉션되기 전에 두 번 클릭해야합니다. 또한 환영 페이지 (로그인 페이지)에서 세션이 만료 될 때. 다음과 같은 오류에서와 같이 응용 프로그램 충돌 :jsf에서 세션이 시작되면 환영 페이지로 돌아갑니다.

WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception 
javax.faces.application.ViewExpiredException: viewId:/loginpage.xhtml - View /loginpage.xhtml could not be restored. 
     at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:205) 
     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
     at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116) 
     at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 
     at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
     at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
     at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
     at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) 
     at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) 
     at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) 
     at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174) 
     at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) 
     at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) 
     at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) 
     at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
     at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
     at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
     at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
     at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
     at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
     at java.lang.Thread.run(Thread.java:662) 

내가 primefaces 3.0, 넷빈즈에 글래스 피쉬 3.1.1 감사를 사용합니다.

+0

을 web.xml에하는 얼굴-config.xml 파일에

추가는 당신이 –

답변

1

사용자가 인증되지 않은 경우 로그인 페이지로 리디렉션하기 위해 서블릿 필터 또는 JSF 위상 수신기를 사용할 수 있습니다.

+0

JSF 단계 리스너이 매우 이상적인 솔루션이 아닙니다 우리 세션 리스너에게 보여해야한다고 생각 케이스. 서블릿 필터를 사용해야합니다. – Apurv

0

우리는 우리의 응용 프로그램에서 비슷한 문제가있었습니다. 아래는 우리가 사용 해본 솔루션입니다. 만료 된 세션의 경우 로그인 페이지로 리디렉션하기 위해 위상 수신기를 사용합니다 (로그인 페이지에없는 경우). 그런 다음 사용자 정의보기 처리기를 사용하여 사용자가 로그인 페이지에서 만료 된 세션을 경험하지 못하게합니다. 기본적으로 로그인 페이지에서 세션이 만료 된 것으로 확인되면 새 세션을 만듭니다.

참고 : 특정 사용 사례에 맞게 업데이트해야하는 코드 부분이 표시되어 있습니다. 우리는 온라인에서 발견 한 특정 문제에 대한 몇 가지 예를 모아이 접근법을 제안했습니다. 참조 중 일부는 다음과 같습니다

http://www.gregbugaj.com/?p=164

https://stackoverflow.com/a/6816513/2212458

다음

https://stackoverflow.com/a/4992869/2212458

는 방문자가 세션이 있는지 확인하기 및 로그인 페이지로 전달을 담당하는 단계 리스너의 경우 그들이 돈 하나가 있습니다 (예 : 만료 된 경우). 또한 2 가지 다른 검사를 수행합니다. 그들은 세션이 있는지, 인증 (로그인)되어 있는지 확인하고, 그들이 그들이 치는 페이지에 대한 액세스 권한이 있는지 확인합니다.

import javax.faces.application.NavigationHandler; 
import javax.faces.context.FacesContext; 
import javax.faces.event.*; 
import javax.servlet.http.HttpSession; 

/** 
* A phase listener. Runs after the restore view phase. Makes sure that the user is logged on 
* to view any page other than the login page. 
*/ 
public class AuthorizationListener implements PhaseListener 
{ 
    /** 
    * Called after phase executes. Makes sure we are logged in if we are not on the login page. 
    * @param phaseEvent 
    */ 
    @Override 
    public void afterPhase(PhaseEvent phaseEvent) 
    { 
     // get page we are on 
     FacesContext facesContext = phaseEvent.getFacesContext(); 
     String currentPage = facesContext.getViewRoot().getViewId(); 

     // determine if we are on the login page 
     boolean isLoginPage = currentPage.contains("login"); <--- CHANGE 
     if (isLoginPage) 
     { 
      return; 
     } 

     // get session - do not create one if it does not exist 
     HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false); 

     // no session is present 
     if(session==null) 
     { 
      NavigationHandler nh = facesContext.getApplication().getNavigationHandler(); 
      nh.handleNavigation(facesContext, null, "login?faces-redirect=true&reason=expired"); <--- CHANGE 
      return; 
     } 

     // if not logged in send to login page 
     if (USER IS NOT LOGGED IN) <--- CHANGE 
     { 
      NavigationHandler nh = facesContext.getApplication().getNavigationHandler(); 
      nh.handleNavigation(facesContext, null, "login?faces-redirect=true&reason=expired"); <--- CHANGE 
      return; 
     } 

     // they are logged in, make sure they have rights to page they are visiting 
     if (USE DOES NOT HAVE RIGHTS TO THE PAGE THEY ARE VISITING) <--- CHANGE 
     { 
      // user does not have privilege to go to this page 
      NavigationHandler nh = facesContext.getApplication().getNavigationHandler(); 
      nh.handleNavigation(facesContext, null, accessDenied); <--- CHANGE 
     } 
    } 

    /** 
    * Called before phase executes. Does nothing. 
    * @param phaseEvent the phase event 
    */ 
    @Override 
    public void beforePhase(PhaseEvent phaseEvent) 
    { 
     // intentionally left blank 
    } 

    /** 
    * Identifies the phase we want to listen and respond to. 
    * @return the phase 
    */ 
    @Override 
    public PhaseId getPhaseId() 
    { 
     return PhaseId.RESTORE_VIEW; 
    } 
} 

다음은 로그인 페이지에서 세션 만료를 중지하는 사용자 정의보기 처리기입니다.

import javax.faces.application.ViewHandler; 
import javax.faces.application.ViewHandlerWrapper; 
import javax.faces.component.UIViewRoot; 
import javax.faces.context.FacesContext; 
import java.io.IOException; 

/** 
* This class adds additional behavior to the facelet view handler. Specifically it 
* prevents the user from experiencing session/view timeout errors at the login screen. 
*/ 
public class CustomViewHandler extends ViewHandlerWrapper 
{ 
    /** The default view handler we are adding extra behavior to. */ 
    private ViewHandler wrapped; 

    /** 
    * Constructor. 
    * @param wrapped the wrapped handler. Ref. 
    */ 
    public CustomViewHandler(ViewHandler wrapped) 
    { 
     super(); 
     this.wrapped = wrapped; 
    } 

    /** 
    * Expose the wrapped handler (required by base class). 
    * @return the handler. Ref. 
    */ 
    @Override 
    public ViewHandler getWrapped() 
    { 
     return wrapped; 
    } 

    /** 
    * Called when a view is restored. Prevents expiration on login page. 
    * @param facesContext the context for this request 
    * @param viewId the view identifier for the current request 
    * @return the restored view 
    */ 
    @Override 
    public UIViewRoot restoreView(FacesContext facesContext, String viewId) 
    { 
     // have the wrapped handler restore the view 
     UIViewRoot root = super.restoreView(facesContext, viewId); 

     // if there was no view to restore (maybe because it expired) 
     if (root == null) 
     { 
      // if the view expired on the login page make a new view, don't allow login page to expire 
      if (viewId.contains("login")) <--- CHANGE 
      { 
       // create a new view 
       // for some reason the starting slash is required else we get errors in server log about not finding the page 
       root = createView(facesContext, "/" + "login"); <--- CHANGE 
       // saves view - without this session never gets created so we will just keep hitting this code 
       facesContext.renderResponse(); 
      } 
     } 

     return root; 
    } 

    /** 
    * Called when a view is rendered. Does nothing but log a message. 
    * @param context the context for this request 
    * @param viewToRender the view to render 
    * @throws IOException thrown if an input/output error occurs in wrapped handler 
    */ 
    @Override 
    public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException 
    { 
     super.renderView(context, viewToRender); 
    } 
} 

이 코드를 사용하려면 설정 파일을 변경해야합니다.

<view-handler>PACKAGE.CustomViewHandler</view-handler> <--- CHANGE 
<lifecycle> 
    <phase-listener>PACKAGE.AuthorizationListener</phase-listener> <--- CHANGE 
</lifecycle> 

추가가

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/login.xhtml?reason=expired</location> <--- CHANGE 
</error-page>-<session-config><session-timeout> 10 </session-timeout></session-config> 
<listener><listener-class> com.sun.faces.config.ConfigureListener </listener-class></listener> 
관련 문제