ExtJS 4: Gerenciamento de Sessão: Session Timeout
Ei pessoal,
Uma pergunta que recebo bastante por email e nas palestras sobre ExtJS que ministro é: Como fazer gerenciamento de sessão usando ExtJS 4? Bem, nesse post vamos tratar justamente sobre esse assunto através de um exemplo prático!
O exemplo desse post irá mostrar uma mensagem para o usuário perguntando se deseja continuar com a sessão aberta, e caso positivo, a app vai cutucar o servidor para manter a sessão ativa; caso negativo, a app automaticamente faz logout. Essa janela vai ficar 1 minuto aberta; caso o usuário não tome nenhuma decisão, também faz logout. A sessão se torna inativa caso o usuário não tome nenhuma ação em uma quantidade de tempo (exemplo: 15 minutos), isso inclui digitar alguma coisa no teclado ou mexer o mouse:
A classe que faz toda essa mágica está aqui:
[code lang="js" firstline="1" toolbar="true" collapse="false" wraplines="false"]<br />/**<br /><%%KEEPWHITESPACE%%> * Session Monitor task, alerts the user that their session will expire in 60 seconds and provides<br /><%%KEEPWHITESPACE%%> * the options to continue working or logout. If the count-down timer expires, the user is automatically<br /><%%KEEPWHITESPACE%%> * logged out.<br /><%%KEEPWHITESPACE%%> */<br />Ext.define('MyApp.widgets.SessionMonitor', {<br /><%%KEEPWHITESPACE%%> singleton: true,<br /><br /><%%KEEPWHITESPACE%%> interval: 1000 * 10, // run every 10 seconds.<br /><%%KEEPWHITESPACE%%> lastActive: null,<br /><%%KEEPWHITESPACE%%> maxInactive: 1000 * 60 * 15, // 15 minutes of inactivity allowed; set it to 1 for testing.<br /><%%KEEPWHITESPACE%%> remaining: 0,<br /><%%KEEPWHITESPACE%%> ui: Ext.getBody(),<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Dialog to display expiration message and count-down timer.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> window: Ext.create('Ext.window.Window', {<br /><%%KEEPWHITESPACE%%> bodyPadding: 5,<br /><%%KEEPWHITESPACE%%> closable: false,<br /><%%KEEPWHITESPACE%%> closeAction: 'hide',<br /><%%KEEPWHITESPACE%%> modal: true,<br /><%%KEEPWHITESPACE%%> resizable: false,<br /><%%KEEPWHITESPACE%%> title: 'Session Timeout Warning',<br /><%%KEEPWHITESPACE%%> width: 325,<br /><%%KEEPWHITESPACE%%> items: [{<br /><%%KEEPWHITESPACE%%> xtype: 'container',<br /><%%KEEPWHITESPACE%%> frame: true,<br /><%%KEEPWHITESPACE%%> html: "Your session will automatically expires after 15 minutes of inactivity. If your session expires, any unsaved data will be lost and you will be automatically logged out. </br></br>If you want to continue working, click the 'Continue Working' button.</br></br>"<br /><%%KEEPWHITESPACE%%> },{<br /><%%KEEPWHITESPACE%%> xtype: 'label',<br /><%%KEEPWHITESPACE%%> text: ''<br /><%%KEEPWHITESPACE%%> }],<br /><%%KEEPWHITESPACE%%> buttons: [{<br /><%%KEEPWHITESPACE%%> text: 'Continue Working',<br /><%%KEEPWHITESPACE%%> handler: function() {<br /><%%KEEPWHITESPACE%%> Ext.TaskManager.stop(MyApp.widgets.SessionMonitor.countDownTask);<br /><%%KEEPWHITESPACE%%> MyApp.widgets.SessionMonitor.window.hide();<br /><%%KEEPWHITESPACE%%> MyApp.widgets.SessionMonitor.start();<br /><%%KEEPWHITESPACE%%> // 'poke' the server-side to update your session.<br /><%%KEEPWHITESPACE%%> Ext.Ajax.request({<br /><%%KEEPWHITESPACE%%> url: 'user/poke.action'<br /><%%KEEPWHITESPACE%%> });<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> },{<br /><%%KEEPWHITESPACE%%> text: 'Logout',<br /><%%KEEPWHITESPACE%%> action: 'logout',<br /><%%KEEPWHITESPACE%%> handler: function() {<br /><%%KEEPWHITESPACE%%> Ext.TaskManager.stop(MyApp.widgets.SessionMonitor.countDownTask);<br /><%%KEEPWHITESPACE%%> MyApp.widgets.SessionMonitor.window.hide();<br /><br /><%%KEEPWHITESPACE%%> // find and invoke your app's "Logout" button.<br /><%%KEEPWHITESPACE%%> Ext.ComponentQuery.query('button[action="buttonLogout"]')[0].fireEvent('click');<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }]<br /><%%KEEPWHITESPACE%%> }),<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Sets up a timer task to monitor for mousemove/keydown events and<br /><%%KEEPWHITESPACE%%> * a count-down timer task to be used by the 60 second count-down dialog.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> constructor: function(config) {<br /><%%KEEPWHITESPACE%%> var me = this;<br /><br /><%%KEEPWHITESPACE%%> // session monitor task<br /><%%KEEPWHITESPACE%%> this.sessionTask = {<br /><%%KEEPWHITESPACE%%> run: me.monitorUI,<br /><%%KEEPWHITESPACE%%> interval: me.interval,<br /><%%KEEPWHITESPACE%%> scope: me<br /><%%KEEPWHITESPACE%%> };<br /><br /><%%KEEPWHITESPACE%%> // session timeout task, displays a 60 second countdown<br /><%%KEEPWHITESPACE%%> // message alerting user that their session is about to expire.<br /><%%KEEPWHITESPACE%%> this.countDownTask = {<br /><%%KEEPWHITESPACE%%> run: me.countDown,<br /><%%KEEPWHITESPACE%%> interval: 1000,<br /><%%KEEPWHITESPACE%%> scope: me<br /><%%KEEPWHITESPACE%%> };<br /><%%KEEPWHITESPACE%%> },<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Simple method to register with the mousemove and keydown events.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> captureActivity : function(eventObj, el, eventOptions) {<br /><%%KEEPWHITESPACE%%> this.lastActive = new Date();<br /><%%KEEPWHITESPACE%%> },<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Monitors the UI to determine if you've exceeded the inactivity threshold.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> monitorUI : function() {<br /><%%KEEPWHITESPACE%%> var now = new Date();<br /><%%KEEPWHITESPACE%%> var inactive = (now - this.lastActive);<br /><br /><%%KEEPWHITESPACE%%> if (inactive >= this.maxInactive) {<br /><%%KEEPWHITESPACE%%> this.stop();<br /><br /><%%KEEPWHITESPACE%%> this.window.show();<br /><%%KEEPWHITESPACE%%> this.remaining = 60; // seconds remaining.<br /><%%KEEPWHITESPACE%%> Ext.TaskManager.start(this.countDownTask);<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> },<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Starts the session timer task and registers mouse/keyboard activity event monitors.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> start : function() {<br /><%%KEEPWHITESPACE%%> this.lastActive = new Date();<br /><br /><%%KEEPWHITESPACE%%> this.ui = Ext.getBody();<br /><br /><%%KEEPWHITESPACE%%> this.ui.on('mousemove', this.captureActivity, this);<br /><%%KEEPWHITESPACE%%> this.ui.on('keydown', this.captureActivity, this);<br /><br /><%%KEEPWHITESPACE%%> Ext.TaskManager.start(this.sessionTask);<br /><%%KEEPWHITESPACE%%> },<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Stops the session timer task and unregisters the mouse/keyboard activity event monitors.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> stop: function() {<br /><%%KEEPWHITESPACE%%> Ext.TaskManager.stop(this.sessionTask);<br /><%%KEEPWHITESPACE%%> this.ui.un('mousemove', this.captureActivity, this); // always wipe-up after yourself...<br /><%%KEEPWHITESPACE%%> this.ui.un('keydown', this.captureActivity, this);<br /><%%KEEPWHITESPACE%%> },<br /><br /><%%KEEPWHITESPACE%%> /**<br /><%%KEEPWHITESPACE%%> * Countdown function updates the message label in the user dialog which displays<br /><%%KEEPWHITESPACE%%> * the seconds remaining prior to session expiration. If the counter expires, you're logged out.<br /><%%KEEPWHITESPACE%%> */<br /><%%KEEPWHITESPACE%%> countDown: function() {<br /><%%KEEPWHITESPACE%%> this.window.down('label').update('Your session will expire in ' + this.remaining + ' second' + ((this.remaining == 1) ? '.' : 's.') );<br /><br /><%%KEEPWHITESPACE%%> --this.remaining;<br /><br /><%%KEEPWHITESPACE%%> if (this.remaining < 0) {<br /><%%KEEPWHITESPACE%%> this.window.down('button[action="logout"]').handler();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }<br /><br />});<br />[/code]
Vamos ver alguns detalhes importantes:
- linha 11: maxInactive - tempo de inatividade do usuário para inativar a sessão. Nesse caso, o valor padrão são de 15 minutos, mas você pode mudar esse valor para a quantidade de tempo que você deseja (em minutos).
- linha 29: html - mensagem que será mostrada para o usuário na janela. Está em inglês, mas você pode traduzir para português se desejar.
- linha 42: url - aqui você vai colocar a url para "cutucar" o servidor para manter a sessão ativa no server também.
- linha 53: aqui colocamos o selector a ser chamado para disparar o evento de logout automaticamente. Nesse exemplo, repare que tem um botão de logout, e essa linha chama exatamente a função que faz logut (nesse exemplo é apenas um alert, mas isso você deve tratar como deseja na sua aplicação). Só um detalhe: não chame a action do seu botão de logut de logout, pois este já está sendo usado por essa classe.
Bem pessoal, é isso!
Se quiser usar essa classe na sua aplicação, basta chamar MyApp.widgets.SessionMonitor.start(). Se estiver usando a arquitetura MVC, coloque isso dentro da função launch da app. No final desse post tem um exemplo de uma app usando essa classe.
Código Fonte Completo: https://github.com/loiane/extjs4-session-timeout
Disclaimer: eu não sou autora desse código, portando, qualquer problema reclame nessa thread do fórum da Sencha: http://www.sencha.com/forum/showthread.php?195957-Session-Timeout-Alert-using-PHP-amp-Extjs4
Até a próxima! :)