Lift / Jetty的绝对会话超时

时间:2013-08-23 13:00:34

标签: jetty lift session-timeout

在Jetty下运行的Lift应用程序中实现绝对会话超时的好方法是什么?

我已经有一个空闲超时,但我希望会话最终超时,即使用户永远不会空闲。

2 个答案:

答案 0 :(得分:1)

首先:您应该了解在活动组件运行时销毁会话的效果(如comet-actors,ajax-requests,...)。但是,一旦检测到会话无效,您就可以创建一个客户端脚本,该脚本会重定向到您身边的开始/警告页面。 LiftRules.noCometSessionCmdLiftRules.noAjaxSessionCmd是您的朋友。

现在:您希望利用提升SessionMaster.sessionCheckFuncs提供给您的机制。每隔10秒运行此方法并为您提供所有当前有效的会话。决不!存储对会话本身的引用。这就是为什么电梯为您提供了一个我们可以利用的唯一标识符。解决方案基于David Pollack的代码来杀死高流量峰值会话,您可以在此处找到:https://www.assembla.com/wiki/show/liftweb/Sessions

在你的Boot.scala中添加:

// append forced session timeout to list of checker-funcs
SessionMaster.sessionCheckFuncs = SessionMaster.sessionCheckFuncs 
  ::: List(ForcedSessionTimeout)

然后在你的lib包中:

import net.liftweb.common._
import net.liftweb.http.SessionInfo
import net.liftweb.util.Helpers._

object ForcedSessionTimeout extends 
   Function2[Map[String, SessionInfo], SessionInfo => Unit, Unit] 
   with Loggable {

  @volatile var sessionTimeoutMillis: Long = 30 * 60 * 1000 // 30 minutes

  private var firstSeen: Map[String, Long] = Map.empty

  def apply(sessions: Map[String, SessionInfo], destroyer: SessionInfo => Unit): Unit = {
    logger.info("Session check!")
    val timeoutThreshold = millis - sessionTimeoutMillis

    val newFirstSeen: Map[String, Long] = sessions.map {
      case (name, si @ SessionInfo(session, agent, _, cnt, lastAccess)) =>
        firstSeen.get(name) match {
          case Some(firstTimeSeen) =>
            if (firstTimeSeen < timeoutThreshold) {
              logger.info(s" Session $name expired after forced session timeout")
              destroyer(si)
            }
            name -> firstTimeSeen

          case None =>
            // add to first seen list
            name -> millis
        }
    }
    // update first seen map, this prevents a leak if we added a session to the map
    // but lift already expired the session for another reason
    this.firstSeen = newFirstSeen
  }
}

答案 1 :(得分:0)

我会使用Lifts feautures从头开始构建你想要的东西。一些想法如下:

使用带有TimeoutStorage的SessionVar(见下文)

将此存储定义为:

class TimeoutStorage[T] {
    private var inner: Option[(T, Long)] = None // the last argument is when the data was set
    def set {} // set the value. If you want to clear the memory as fast as possible, schedule an erase. Otherwise it would be erased with the `SessionVar` anyway.
    def get{} // check if it has expired
}

如果你想为用户提供视觉超时 - 添加像@jcern这样的演员说。或者只是net.liftweb.util.Schedule一个将JS发送到浏览器的小函数(这必须是可能的,一个人应该注意,而不是适当的net.liftweb.http.S在范围内)。