【问题标题】:Redirect to different page after session expires会话到期后重定向到不同的页面
【发布时间】:2013-07-05 23:07:53
【问题描述】:

我有一个使用这些技术构建的 Web 应用程序:

  • Spring MVC
  • 网络流
  • Spring 安全性
  • Primefaces

并且我需要在会话到期后将用户重定向到不同的页面。经过一番研究,我发现了两种选择。使用带有超时功能的 JavaScript 或 <meta http-equiv="refresh"> 标签。 但是有没有更优雅的方法呢?

我也尝试使用 HttpSessionListener 来做,但我不知道如何将客户端重定向到不同的站点(我不确定是否可能)。

或者是否可以配置 Tomcat 或 Apache 在一段时间后以某种方式刷新客户端视图?

提前致谢。

【问题讨论】:

    标签: spring redirect spring-security spring-webflow


    【解决方案1】:

    一种方法是实现过滤器:
    1) 检查HttpServletRequest.getRequestedSessionId(),如果它返回null,这是一个新请求,否则之前有一个活动会话。
    2) 检查HttpServletRequest.isRequestedSessionIdValid(),如果返回false,则表示会话在服务器端已过期。
    3) 如果需要,从过滤器重定向。

    【讨论】:

    • 我不确定你的意思是什么。你能说得更具体一点吗?
    • 理想情况下,一旦服务器上的会话超时,就不可能重定向用户。但是,在用户的下一个请求中,您可以检查会话有效性并重定向到登录/其他页面。
    • 如果您可以在安全过滤器本身中执行它会很好,但因为我之前没有使用过弹簧安全性。我不知道它的灵活性。
    【解决方案2】:

    这是我用来通知用户会话到期并将用户重定向到“您已注销”页面的代码:

       <h:form prependId="false" style="display:none;">
          <p:idleMonitor
             timeout="#{session.maxInactiveInterval * 1000 - 60000}"
             onidle="startIdleMonitor()"
             onactive="timeoutDialog.hide()" />
    
          <p:dialog id="timeoutSession"
             header="Session expiring..."
             widgetVar="timeoutDialog"
             showEffect="fade" hideEffect="fade"
             modal="true"
             closable="false"
             draggable="false"
             resizable="false"
             appendToBody="true"
             position="center"
             onHide="stopCount()"
             onShow="doTimer()">
             <br />
             <p>
                <span class="ui-icon ui-icon-alert" style="float: left; margin: 8px 8px 0;"/>
                <p:panel>
                   Your session will expire in&nbsp;
                   <span id="dialog-countdown" style="font-weight: bold"></span>
                   &nbsp;seconds
                </p:panel>
             </p>
             <br/>
             <p style="font-weight: bold;">Please move your mouse to keep the session alive</p>
          </p:dialog>
          <p:remoteCommand name="keepAlive" actionListener="#{applicationBean.keepSessionAlive}" />
       </h:form>
       <script type="text/javascript">
          var TIME = 60; // in seconds
          var countTimer = TIME;
          var processTimer;
          var timer_is_on = 0;
          var redirectPage = "#{applicationBean.logoutURL}";
    
          var countDownDiv = "dialog-countdown";
          var txtCountDown = null;
          if (!txtCountDown)
            txtCountDown = document.getElementById(countDownDiv);
    
          function startIdleMonitor() {
            countTimer = TIME;
            txtCountDown.innerHTML = countTimer;
            timeoutDialog.show();
          }
          function timedCount() {
            txtCountDown.innerHTML = countTimer;
            if (countTimer == 0) {
                stopCount();
                window.location.href = redirectPage;
                return;
            }
            countTimer = countTimer - 1;
            processTimer = setTimeout("timedCount()", 1000);
          }
          function doTimer() {
            if (!timer_is_on) {
                timer_is_on = 1;
                timedCount();
            }
          }
          function stopCount() {
            clearTimeout(processTimer);
            timer_is_on = 0;
            keepAlive();
          }
          </script>
    

    【讨论】:

      【解决方案3】:

      我认为确保应用程序处理所有 3 三种情况(登录失败、无效会话和过期会话)是个好主意。在 Spring Security 中执行此操作的一种方法如下:

          <http>
      ...
      <!-- form login if you have one -->
      <form-login authentication-failure-url="/handleLoginFailure" />
           ...
           <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrentSessionFilter" />
      <session-management invalid-session-url="/handleSessionNoLongerActive" session-authentication-strategy-ref="concurrentSessionControlStrategy" />
      
      </http>
      
      
      
      <beans:bean id="concurrentSessionFilter" 
          class="org.springframework.security.web.session.ConcurrentSessionFilter" 
          c:sessionRegistry-ref="sessionRegistry" 
          c:expiredUrl="/handleSessionExpired">
      </beans:bean>
      
      
      @Bean
      public SessionRegistry sessionRegistry() {
          SessionRegistryImpl impl = new SessionRegistryImpl() ;
          return impl;
      }
      
      @Bean
      public ConcurrentSessionControlStrategy concurrentSessionControlStrategy() {
          ConcurrentSessionControlStrategy impl = new ConcurrentSessionControlStrategy(sessionRegistry()) ;
          return impl;
      }   
      

      另见Session Management。 (web.xml 更改)。

      根据应用程序功能,您可能还需要处理拒绝访问的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多