Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the expiration time for a cookie managed by Plack::Middleware::Session?

Now my app.psgi contains (simplified):

builder {
      enable 'Session', store => 'File'; #default uses Plack::Session::State::Cookie
      $app;
};

Later, in the $app I'm using:

my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";

It works ok, e.g.:

  • when the user logged in, I store his name in the server-side stored session-file, and the Plack::Middleware::Session sets an simple session-state-cookie,
  • and when the user closing the browser, the cookie is automatically cleared (because the Plack::Session::State::Cookie by default didn't set any expiration for the cookie).

Now, I want implement the "Remember me" feature in my login-panel. In this case, the sesion-state-cookie should-not be removed automatically from the browser. This can be done, by using the expires method from the Plack::Session::State::Cookie.

The question:

How I can change the cookie expiration (managed by the Session middleware) from my $app. With other words, how to call the expire method somewhat here:

my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";
my $cookie_state = WHAT_TO_DO_HERE_TO_GET; #the current Plack::Session::State::Cookie object
$cookie_state->expire(86400*14); #expire in two weeks

If someone needs, here is an working example.

use strict;
use warnings;
use Plack::Request;
use Plack::Response;
use Plack::Builder;
use Data::Dumper;

my $app = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;
    my $res = Plack::Response->new(200);
    $res->content_type('text/html');
    my $link = $session->{user}
            ? q{ <a href="/logout">logout</a>}
            : q{ <a href="/login">login</a>}
            ;
    $res->body(["Session user:", $session->{user}, "<br>$link"]);
    return $res->finalize;
};

my $login = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;

    $session->{user} = "some";
    #how to set here the session-state-cookie expiration?

    my $res = Plack::Response->new();
    $res->redirect("/", 302);
    return $res->finalize;
};

my $logout = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;
    delete $session->{user};
    my $res = Plack::Response->new();
    $res->redirect("/", 302);
    return $res->finalize;
};

builder {
    enable 'Session', store => 'File';
    mount "/login" => $login; 
    mount "/logout" => $logout; 
    mount "/favicon.ico" => sub { return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ] };
    mount "/" => $app; 
};
like image 875
kobame Avatar asked Mar 21 '15 20:03

kobame


People also ask

How do cookies expire at end of session?

To set a cookie so it expires at the end of the browsing session, simply OMIT the expiration parameter altogether.

What is cookie expiration session?

Session cookies expire once you log off or close the browser. They are only stored temporarily and are destroyed after leaving the page. They are also known as transient cookies, non-persistent cookies, or temporary cookies.

How do you set cookie max age?

Java HttpCookie setMaxAge() MethodThe setMaxAge(long expiry)method of Java HttpCookie class is used to set the maximum age of the cookie within seconds. The result with a positive value indicates that the cookie will expire after the specified time in seconds.

How long do web application session cookies expire?

Answer. Yes the Session cookie expires. In addition to the 30 minute default timeout (if the visitor is idle for 30 minutes) the 'Session ID' cookie will expire at the end of an internet browser session.


1 Answers

You can't change the expiration date directly, but you can force the session middleware to create a new session with a new expiration date like this:

$env->{'psgix.session.options'}{change_id} = 1;
$env->{'psgix.session.options'}{expires}   = $my_expires;

If a user logs in, you should change the ID anyway to prevent session fixation attacks. See Cookie::Baker for supported expiration date formats.

EDIT: If you want to set the default expiration timeout globally, you can build the state object manually and pass the expires parameter to the constructor:

builder {
    enable 'Session',
        state => Plack::Session::State->new(
            expires => $timeout_in_seconds,
        );
    $app;
};
like image 180
nwellnhof Avatar answered Oct 19 '22 04:10

nwellnhof