How to add timestamp into my user session and set

2019-04-13 03:23发布

I handled session using Play framework in my application like below code.

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"))
    }

  }

I need to add timeout for my session. In Play documentation,

There is no technical timeout for the session, which expires when the user closes the web browser. If you need a functional timeout for a specific application, just store a timestamp into the user Session and use it however your application needs (e.g. for a maximum session duration, maxmimum inactivity duration, etc.).

How to add timestamp into my user session and set maximum insctivity duration?

3条回答
做个烂人
2楼-- · 2019-04-13 03:37

To Configure timeout in your Play application by setting values for configuration keys in conf/application.conf file.

application.session.maxAge

Session time-out, i.e. the maximum age of the session cookie. If not set, the session expires when you close your web browser. For example, to set the session to one hour:

application.session.maxAge=1h

Remember the session for one week:

application.session.maxAge=7d

Default: the session is based on a transient cookie expires when the browser is closed.

or You can do something like :

During your login set a "last action time" to current time in the session.

In your Global class, override onRequest test if that flag exist

  • if not, user has no session -> redirect to login silently

  • if yes

    --- test if last time is more than 30min ago

         ------ if yes, session timeout -> add message to flash, rediect to login   
         ------ if no, update the flag with current time, let the page load
    
查看更多
仙女界的扛把子
3楼-- · 2019-04-13 03:44

I did something like @arseniy-zhizhelev suggested

I had this same problem and added a timestamp (tick) to the session and updated it with each request after checking for a timeout.

Something like this:

// 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/

Then add a sessionTimeout=15 (in Minutes) to your conf file.

查看更多
来,给爷笑一个
4楼-- · 2019-04-13 03:45

I would do it as follows. On every answer to the user I would write the current time to the session:

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

To ensure proper session time and email/password I would add an Action extension like this:

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

The Action extension is used as follows:

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

(you may have a look at https://github.com/Primetalk/todo-list/blob/master/app/controllers/SecuredController.scala and it's usage at https://github.com/Primetalk/todo-list/blob/master/app/controllers/Task.scala).

UPD:(regards to @kliron) The above withSession will replace the whole session. If you need to store there some other info, then you need to save it:

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

and

def index = withEmail(email => 
   Action { request =>
     Ok(views.html.index(email)).withSession(session + "currentTime" -> System.currentTimeMillis)
   }
)
查看更多
登录 后发表回答