在Jetty下运行的Lift应用程序中实现绝对会话超时的好方法是什么?
我已经有一个空闲超时,但我希望会话最终超时,即使用户永远不会空闲。
答案 0 :(得分:1)
首先:您应该了解在活动组件运行时销毁会话的效果(如comet-actors,ajax-requests,...)。但是,一旦检测到会话无效,您就可以创建一个客户端脚本,该脚本会重定向到您身边的开始/警告页面。 LiftRules.noCometSessionCmd
和LiftRules.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
在范围内)。