不活动后会话自动注销

时间:2016-07-01 11:14:01

标签: node.js express express-session

快递会话中是否有内置功能,以便在给定的不活动时间后启用自动注销?我正在使用它如下所示,如果会话处于非活动状态半小时,则希望它注销。

app.use(session({
  key: 'sessid',
  secret: 'This is secret',
  resave: true,
  saveUninitialized: true,
  store: new RedisStore(redisOptions),
  cookie: {
    path: '/',
    httpOnly: true,
    secure: false,
    maxAge: 24 * 60 * 60 * 1000,
    signed: false
  }
}))

2 个答案:

答案 0 :(得分:6)

好的,我会把我的两分钱扔进戒指。

即使理论上可以使用rolling session来实现这一点,但我认为你不应该...

  • 这将要求每个用户操作向服务器发送请求,以便用户不被注销。
  • 您错过了通知您的用户他/她将很快自动退出的机会(例如银行所做的事情)。
    @Seth在上面的评论中指出实际上有一种方法可以解决这个问题:“如果前端与服务器分开,你可以使用客户端路由中间件来检查cookie并直观地将你注销,从而证明了良好的用户体验。“
    我认为这很聪明,但我也认为这就像把口红涂在猪身上一样。

我认为这里最好的方法是在client side处理此问题。

我会建议这样的事情:

var AutoLogout = (function() {
  function AutoLogout() {
    this.events = ['load', 'mousemove', 'mousedown',
                   'click', 'scroll', 'keypress'];

    this.warn = this.warn.bind(this);
    this.logout = this.logout.bind(this);
    this.resetTimeout = this.resetTimeout.bind(this);

    var self = this;
    this.events.forEach(function(event) {
      window.addEventListener(event, self.resetTimeout);
    });

    this.setTimeout();
  }

  var _p = AutoLogout.prototype;

  _p.clearTimeout = function() {
    if(this.warnTimeout)
      clearTimeout(this.warnTimeout);

    if(this.logoutTimeout)
      clearTimeout(this.logoutTimeout);
  };

  _p.setTimeout = function() {
    this.warnTimeout = setTimeout(this.warn, 29 * 60 * 1000);

    this.logoutTimeout = setTimeout(this.logout, 30 * 60 * 1000);
  };

  _p.resetTimeout = function() {
    this.clearTimeout();
    this.setTimeout();
  };

  _p.warn = function() {
    alert('You will be logged out automatically in 1 minute.');
  };

  _p.logout = function() {
    // Send a logout request to the API
    console.log('Sending a logout request to the API...');

    this.destroy();  // Cleanup
  };

  _p.destroy = function() {
    this.clearTimeout();

    var self = this;
    this.forEach(function(event) {
      window.removeEventListener(event, self.resetTimeout);
    });
  };

  return AutoLogout;
})();

ES2015

class AutoLogout {
  constructor() {
    this.events = ['load', 'mousemove', 'mousedown',
                   'click', 'scroll', 'keypress'];

    this.warn = this.warn.bind(this);
    this.logout = this.logout.bind(this);
    this.resetTimeout = this.resetTimeout.bind(this);

    this.events.forEach((event) => {
      window.addEventListener(event, this.resetTimeout);
    });

    this.setTimeout();
  }

  clearTimeout() {
    if(this.warnTimeout)
      clearTimeout(this.warnTimeout);

    if(this.logoutTimeout)
      clearTimeout(this.logoutTimeout);
  }

  setTimeout() {
    this.warnTimeout = setTimeout(this.warn, 29 * 60 * 1000);

    this.logoutTimeout = setTimeout(this.logout, 30 * 60 * 1000);
  }

  resetTimeout() {
    this.clearTimeout();
    this.setTimeout();
  }

  warn() {
    alert('You will be logged out automatically in 1 minute.');
  }

  logout() {
    // Send a logout request to the API
    console.log('Sending a logout request to the API...');

    this.destroy();  // Cleanup
  }

  destroy() {
    this.clearTimeout();

    this.events.forEach((event) => {
      window.removeEventListener(event, this.resetTimeout);
    });
  }
}

部分民意调查解决方案:

var activityPolling = (function() {
  var events = ['load', 'mousemove', 'mousedown', 'click', 'scroll', 'keypress'];
  var active = true;
  var timeout;

  function poll() {
    if(active) {
      console.log('polling the server...')
    }
  }

  function setIdle() {
    active = false;
  }

  function setActive() {
    active = true;
    if(timeout)
      clearTimeout(timeout);
    timeout = setTimeout(setIdle, 30 * 60 * 1000);
  }

  function destroy() {
    clearInterval(interval);

    events.forEach(function(event) {
      window.removeEventListener(event, setActive);
    });
  }

  events.forEach(function(event) {
    window.addEventListener(event, setActive);
  });

  setActive();

  var interval = setInterval(poll, 60 * 1000);

  return {
    interval: interval,
    destroy: destroy
  }
})();

答案 1 :(得分:0)

Rolling session可以解决目的。

如果您将会话的“滚动”选项用于“true”,它将更新新请求的会话超时。

您可以做的是:将max-age设置为5分钟。

 maxAge: 30*10000

当没有活动时,max-age会破坏会话。 但是,当有任何活动时,滚动会使会话在接下来的30分钟内更新。

同样,这个问题中的活动这个词有点误导。 活动可以是任何(或全部)无鼠标移动,无鼠标点击或与服务器无交互。
如果您将不活动称为无与服务器的交互,则此逻辑将起作用。但是,对于无ui交互不活动,您需要从客户端处理