Effectuer automatiquement l'action côté client lorsque la session expire

je veux afficher dans un <p:growl> que la session a expiré. J'ai trouvé de nombreuses méthodes pour gérer l'expiration de session comme temporisation de la Session et gestion de la réception ViewExpiredException sur la requête ajax JSF / PrimeFaces, mais je ne pouvais pas pousser un visages message <p:growl>.

au point, Comment puis-je exécuter automatiquement du code (JavaScript) côté client alors que la session HTTP est automatiquement expirée côté serveur?

10
demandé sur BalusC 2013-09-30 19:03:37

3 réponses

vous pouvez utiliser PrimeFaces idle moniteur pour cela. L'utilisateur est redirigé vers l'action logout après timeout pour invalider la session. 2 minutes avant qu'une boîte de dialogue compte à rebours s'affiche pour avertir l'utilisateur. Après avoir remué la souris, la session est prolongée.

PrimeFaces ralenti surveiller et boîte de dialogue est placé dans un modèle, vous pouvez ajouter à chaque page qui est en cause:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:p="http://primefaces.org/ui">

<ui:composition>
   <h:form prependId="false">
      <p:idleMonitor
     timeout="#{session.maxInactiveInterval * 1000 - 125000}"
     onidle="startIdleMonitor()"
     onactive="timeoutDialog.hide()" />

      <p:dialog id="timeoutSession"
     header="#{msg['session.expire']}"
     widgetVar="timeoutDialog"
     showEffect="fade" hideEffect="fade"
     modal="true"
     width="400"
     height="110"
     closable="false"
     draggable="false"
     resizable="false"
     appendToBody="true"
     onHide="stopCount()"
     onShow="doTimer()">
     <br />
     <p>
        <span class="ui-icon ui-icon-alert" style="float: left; margin: 8px 8px 0;"/>
        <p:panel>
           #{msg['logoff.soon.1']}
           <span id="dialog-countdown" style="font-weight: bold"></span>
           #{msg['logoff.soon.2']}
        </p:panel>
     </p>
     <br />
     <p style="font-weight: bold;">#{msg['move.cursor']}</p>
      </p:dialog>
      <p:remoteCommand name="keepAlive" actionListener="#{auth.keepSessionAlive}" />
   </h:form>
   <script type="text/javascript">
      var TIME = 120; // in seconds
      var countTimer = TIME;
      var processTimer;
      var timer_is_on = 0;
      var redirectPage = "#{request.contextPath}/auth/j_verinice_timeout";

      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>
</ui:composition>
</html>
  • ligne 11: le temps d'arrêt du moniteur de ralenti est réglé par le système var session.maxInactiveInterval. La valeur que vous mettez dans votre web.xml ou la configuration du serveur.
  • ligne 12/13: la méthode Javascript startIdleMonitor () est appelée après la fin du délai sans aucune interaction de l'utilisateur. Cette méthode ouvre le dialogue. timeoutDialog.masquer() est appelé lorsque l'utilisateur est occupé à nouveau: le dialogue est fermé
  • ligne 26/27: deux autres méthodes Javascript sont utilisées lorsque la boîte de dialogue s'affiche ou se cache.: doTimer () commence et stopCount () arrête le compte à rebours.
  • ligne 40: Commande À Distance PrimeFaces pour maintenir la session en vie. En appelant une méthode arbitraire sur le serveur de la séance est prolongée. La commande est appelée par la méthode Javascript keepAlive () à la ligne 78.
  • ligne 59-68: méthode Javascript timedCount () est appelée à chaque seconde pour exécuter le compte à rebours. Après le délai de redirection est fait dans la ligne 63.

pour activer la gestion du délai d'attente dans plusieurs pages, incluez le modèle de délai d'attente dans votre modèle de mise en page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xml:lang="de-DE">
<h:head>
  ...
</h:head>
<body>
  <ui:include src="/template/sessionTimeOut.xhtml" />
  <ui:include src="/nav.xhtml"/>>
  <ui:insert name="content">Default content</ui:insert>
  <ui:include src="/footer.xhtml"/>>
</body>
</html>

un délai spécifique pour votre application web que vous pouvez définir dans votre web.xml:

<!--?xml version="1.0" encoding="UTF-8"?-->
<web-app>
   ...
   <session-config>
      <!-- Session idle timeout in min. -->
      <session-timeout>30</session-timeout>
    </session-config>
</web-app>

vous pouvez en savoir plus sur cette solution dans ce billet de blog:JSF et PrimeFaces: Délai d'expiration de Session Manipulation

14
répondu uı6ʎɹnɯ ꞁəıuɐp 2017-06-20 14:03:16

si vous êtes sur JSF 2.3, alors vous pouvez utiliser une session scoped <f:websocket> pour cela. Lorsque la session expire côté serveur, alors le <f:websocket> est automatiquement fermée avec code de fermeture 1000 ("fermeture normale").

En d'autres termes, il suffit de faire:

<f:websocket ... scope="session" onclose="sessionScopedSocketCloseListener" />

function sessionScopedSocketCloseListener(code) {
    if (code == 1000) {
        alert("Session has expired!");
    }
}

vous pouvez le combiner si nécessaire avec L'API JavaScript de <p:growl>.

<p:growl widgetVar="growl" ... />

PF("growl").renderMessage({severity: "warn", summary: "Session has expired!" });

Si vous n'êtes pas sur JSF 2.3 encore, alors vous pouvez toujours utiliser <o:socket> au lieu de cela qui offre exactement le même onclose fonctionnalité <f:websocket>. Voir aussi comment le serveur peut-il pousser des changements asynchrones à une page HTML créée par JSF?

8
répondu BalusC 2017-11-21 08:45:18

le code posté par @uı6ʎɹnɯ lǝıuɐp j'ai est très utile, mais je vais ajouter quelques observations:

  • @Jonathan L sugests remplacer processTimer = setTimeout("timedCount()", 1000)setInterval("timedCount()", 1000). Je pense que du bon sens, mais besoin de quelques modifications:

    function doTimer() {
        if (!timer_is_on) {
            timer_is_on = 1;
            processTimer = setInterval("timedCount()", 1000);
        }
    }
    
    function stopCount() {
        clearInterval(processTimer);
        timer_is_on = 0;
        keepAlive();
    }
    

  • La méthode timedCount () peut être changé:

    function timedCount() {
        txtCountDown.innerHTML = countTimer;
        if (countTimer > 0) {
            countTimer = countTimer - 1;
        } else {
            clearInterval(processTimer);
            doLogout();
        }
    }
    

    et vous devez ajouter sous le keepAlive remoteCommand quelque chose comme ceci:

    <p:remoteCommand name="doLogout" action="#{loginMB.logout()}" 
                     process="@this" partialSubmit="true" immediate="true" />
    

    À L'Intérieur De Managed Bean:

    public void logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        validUser = false;
        loggedUser = false;
        redirectToPage("/login.xhtml");
    }
    
    private void redirectToPage(String page) {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        context.redirect(context.getRequestContextPath() + page);
    }
    

    ne pas oublier l'attribut name="doLogout"p:remoteCommand est converti dans une fonction javascript que vous pouvez appeler n'importe où. Il est parfait pour itérer la vue avec des haricots gérés.

    cette approche empêchera votre système empile ViewExpiredException.


  • Certaines personnes ne comprennent pas l' keepAlive concept, mais c'est très facile, il suffit d'ajouter une fonction simple à l'intérieur de votre bean managé. Exemple keepSessionAlive action:

    public void keepSessionAlive () {
        System.out.println(">>> Session is alive... ");
    }
    

    Souvenir p:remoteCommandkeepAlive est une fonction javascript appelée keepAlive() et que l'appel d'une action keepSessionAlive à l'intérieur de votre haricot managé.

    cette action indique que vous n'êtes pas inactif.


  • session.maxInactiveInterval de idleMonitor références <session-timeout> de web.xml

    <p:idleMonitor timeout="#{session.maxInactiveInterval * 1000 - 125000}"
                   onidle="startIdleMonitor()" onactive="timeoutDialog.hide()" />
    

    je recommande à put session monitor d'exécuter 5 secondes avant de terminer la session pour éviter de lancer doLogout() après la fin de la session ViewExpiredException.

    la première ligne du code javascript est var TIME = 120; // in seconds, c'est le temps de finaliser la session. Le code original # {session.maxInactiveInterval * 1000 - 125000} va utiliser session-timeout mutiplicated de 1.000 (parce que c'est milisecondes) et soustraire 125.000 qui représente 125 secondes, 5 secondes de moins que counter, donc n'a pas besoin de changements.


j'espère que cela vous aidera... Bonne Chance!

2
répondu ℛɑƒæĿ 2016-12-09 19:21:15