【问题标题】:How to add timestamp into my user session and set maximum inactivity duration?如何在我的用户会话中添加时间戳并设置最长不活动持续时间?
【发布时间】:2013-11-06 10:36:11
【问题描述】:

我在我的应用程序中使用 Play 框架处理会话,如下面的代码。

def login = Action {
    { implicit request =>

          val email = request.body.asFormUrlEncoded.get("email")(0)
          val password = request.body.asFormUrlEncoded.get("password")(0)

          loginForm.bindFromRequest.fold(
              errors => BadRequest(html.login(errors,"Please enter valid username password")),
              //contact => Ok(html.login(loginForm,SignUpProcess.login(email,password)))
              contact => Redirect(routes.Application.home).withSession("email" -> email,"password" -> password)
          )
      }
  }

  def index = Action { request =>
    request.session.get("email").map{ user =>
        Redirect(routes.Application.home).withSession("email" -> user)
    }.getOrElse{
         Ok(views.html.login(loginForm,"Enter username password to login"))
    }

  }

我需要为我的会话添加超时。在 Play 文档中,

会话没有技术超时,当 用户关闭网络浏览器。如果您需要功能超时 特定应用程序,只需将时间戳存储到用户会话中,然后 根据您的应用程序需要使用它(例如,用于最大会话 持续时间、最长不活动持续时间等)。

如何在我的用户会话中添加时间戳并设置最长不活跃持续时间?

【问题讨论】:

  • .withSession("email" -> user+","+System.currentTimeMillis) 这确实有效。但我想如果功能不断增加,您将不得不开始在服务器上管理用户状态

标签: scala playframework playframework-2.0


【解决方案1】:

通过在 conf/application.conf 文件中设置配置键的值来在 Play 应用程序中配置超时。

application.session.maxAge

会话超时,即会话 cookie 的最大年龄。如果未设置,会话将在您关闭 Web 浏览器时过期。例如,将会话设置为一小时:

application.session.maxAge=1h

记住一周的课程:

application.session.maxAge=7d

默认:会话基于一个临时cookie,当浏览器关闭时过期。

或 您可以执行以下操作:

在您登录期间,将“上次操作时间”设置为会话中的当前时间。

在您的 Global 类中,如果该标志存在,则覆盖 onRequest 测试

  • 如果没有,用户没有会话 -> 重定向到静默登录

  • 如果是的话

    --- 测试最后一次是否超过 30 分钟之前

         ------ if yes, session timeout -> add message to flash, rediect to login   
         ------ if no, update the flag with current time, let the page load
    

【讨论】:

  • 1) 如果我设置 maxAge=1h,即使我的应用程序处于活动状态(用户正在工作),会话也会在 1 小时后过期? 2) 当浏览器关闭时,我的临时 cookie 也不会过期吗?我的会话仍然存在。
  • 超时 10 分钟你应该把 maxAge=1omin 当你把这个我认为默认会话将不起作用,你的应用程序会话将仅活动 10 分钟
  • @Rahul Kulhari "如果没有,用当前时间更新标志,让页面加载" 你将如何从 onGlobalRequest 处理程序中做到这一点?它只能访问请求对象,不能设置任何会话变量。
【解决方案2】:

我做了类似@arseniy-zhizhelev 建议的事情

我遇到了同样的问题,并在会话中添加了时间戳(滴答声),并在检查超时后随每个请求更新它。

类似这样的:

// see if the session is expired
String previousTick = session("userTime");
if (previousTick != null && !previousTick.equals("")) {
  long previousT = Long.valueOf(previousTick);
  long currentT = new Date().getTime();
  long timeout = Long.valueOf(Play.application().configuration().getString("sessionTimeout")) * 1000 * 60;
  if ((currentT - previousT) > timeout) {
    // session expired
    session().clear();
    return null;
  } 
}
// update time in session
String tickString = Long.toString(new Date().getTime());
session("userTime", tickString);

http://www.poornerd.com/2014/04/01/how-to-implement-a-session-timeout-in-play-framework-2/

然后将 sessionTimeout=15(以分钟为单位)添加到您的 conf 文件中。

【讨论】:

    【解决方案3】:

    我会这样做。在对用户的每个回答中,我都会将当前时间写入会话:

    .withSession("currentTime" -> System.currentTimeMillis)
    

    为确保正确的会话时间和电子邮件/密码,我将添加一个 Action 扩展名,如下所示:

    def withEmail(f: String => EssentialAction): EssentialAction =
                Security.Authenticated(
                                currentEmailOpt,
                                r => Redirect(views.html.login(loginForm,"Enter username password to login")) )(f)
    
    private
    def currentEmailOpt(request: RequestHeader): Option[String] = 
        for{
          currentTime <- request.session.get("currentTime")
          deltaMs = System.currentTimeMillis - currentTime.toLong
          if deltaMs < 10*60*1000
          email <- request.session.get("email")
        }
          yield email
    

    Action 扩展名的用法如下:

    def index = withEmail(email => 
       Action { request =>
         Ok(views.html.index(email)).withSession("email" -> email, "currentTime" -> System.currentTimeMillis)
       }
    )
    

    (您可以查看https://github.com/Primetalk/todo-list/blob/master/app/controllers/SecuredController.scala 以及https://github.com/Primetalk/todo-list/blob/master/app/controllers/Task.scala 的用法)。

    UPD:(关于@kliron)上面的withSession 将替换整个会话。如果您需要在那里存储一些其他信息,那么您需要保存它:

    .withSession(session + "currentTime" -> System.currentTimeMillis)
    

    def index = withEmail(email => 
       Action { request =>
         Ok(views.html.index(email)).withSession(session + "currentTime" -> System.currentTimeMillis)
       }
    )
    

    【讨论】:

    • 你不是说 .withSession(session + ("currentTime" -> ...)) 吗?否则 .withSession 将覆盖任何现有的 keyval。
    • playframework.com/documentation/2.0/ScalaSessionFlash 看来会话是由withSession 更新的。要放弃整个会话,需要withNewSession
    • 我从您的链接中引用:“请注意,这将替换整个会话。如果您需要向现有会话添加一个元素,只需向传入会话添加一个元素,并将其指定为新的会议”。更明确地说,使用: .withSession(session + ("key" -> val)) 如果你想保留会话中以前的键值对,或者 .withSession("key"->val) 如果你希望会话仅包含此密钥对。
    • 戳我的生命体征!看来你是对的。我会修复答案。谢谢。
    猜你喜欢
    • 2011-03-14
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2023-01-29
    • 2014-05-22
    • 1970-01-01
    相关资源
    最近更新 更多