Как установить срок действия файла cookie, управляемого Plack::Middleware::Session?

Теперь мой app.psgi содержит (упрощенно):

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

Позже, в $app Я использую:

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

Работает нормально, например:

  • когда пользователь вошел в систему, я сохраняю его имя в файле сеанса, сохраненном на стороне сервера, и https://metacpan.org/pod/Plack::Middleware::Session устанавливает простой cookie-файл session-state,
  • и когда пользователь закрывает браузер, cookie автоматически очищается (потому что https://metacpan.org/pod/Plack::Session::State::Cookie по умолчанию не устанавливает никакого срока действия для cookie).

Теперь я хочу реализовать функцию "Запомнить меня" в моей панели входа в систему. В этом случае cookie-файл состояния sesion не должен автоматически удаляться из браузера. Это можно сделать, используя expires метод из https://metacpan.org/pod/Plack::Session::State::Cookie.

Вопрос:

Как я могу изменить срок действия файлов cookie (управляемый промежуточным программным обеспечением сеанса) из моего $app, Другими словами, как вызвать метод expire здесь:

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

Если кому-то нужно, вот рабочий пример.

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; 
};

1 ответ

Решение

Вы не можете изменить дату истечения срока действия напрямую, но вы можете заставить промежуточное программное обеспечение сеанса создать новый сеанс с новой датой истечения срока действия, например так:

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

Если пользователь входит в систему, вы должны в любом случае изменить идентификатор, чтобы предотвратить атаки с фиксацией сеанса. Увидеть Cookie::Baker для поддерживаемых форматов даты истечения срока действия.

РЕДАКТИРОВАТЬ: Если вы хотите установить глобальный тайм-аут по умолчанию, вы можете построить объект состояния вручную и передать expires Параметр для конструктора:

builder {
    enable 'Session',
        state => Plack::Session::State->new(
            expires => $timeout_in_seconds,
        );
    $app;
};
Другие вопросы по тегам