【问题标题】:How to set the expiration time for a cookie managed by Plack::Middleware::Session?如何为 Plack::Middleware::Session 管理的 cookie 设置过期时间?
【发布时间】:2015-03-21 20:09:55
【问题描述】:

现在我的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";

它工作ok,例如:

  • 当用户登录时,我将他的名字存储在服​​务器端存储的会话文件中,Plack::Middleware::Session 设置了一个简单的会话状态cookie,
  • 并且当用户关闭浏览器时,cookie 会被自动清除(因为Plack::Session::State::Cookie 默认情况下没有为 cookie 设置任何过期时间)。

现在,我想在我的登录面板中实现“记住我”功能。在这种情况下,不应从浏览器中自动删除 session-state-cookie。这可以通过使用Plack::Session::State::Cookie 中的expires 方法来完成。

问题:

如何更改我的 $app 的 cookie 过期时间(由 Session 中间件管理)。换句话说,这里如何调用 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; 
};

【问题讨论】:

    标签: perl session session-cookies middleware plack


    【解决方案1】:

    您不能直接更改过期日期,但可以强制会话中间件创建具有新过期日期的新会话,如下所示:

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

    如果用户登录,您无论如何都应该将 ID 更改为 prevent session fixation attacks。请参阅Cookie::Baker 了解支持的到期日期格式。

    编辑:如果要全局设置默认过期超时,可以手动构建状态对象并将expires参数传递给构造函数:

    builder {
        enable 'Session',
            state => Plack::Session::State->new(
                expires => $timeout_in_seconds,
            );
        $app;
    };
    

    【讨论】:

    • 虽然我预计会有一些方法调用,但它有效。我的问题是,这是在哪里记录的?因为在 Plack::Middleware::Session are documented some subkeys 中为 psgix.session.options 但缺少 expires。 (这里只有expire /没有复数(s)/什么用于使会话无效)。所以真的很想知道你从哪里知道的。通过挖掘模块源?无论如何非常感谢
    • @kobame 是的,我通过查看源代码知道这一点。我打开了一个 GitHub issue 关于缺少的文档。
    • 我想说谢谢你的回复;将在我的应用程序中尝试一下。 github问题没有任何活动,我一直在使用的框架(Kelp)似乎没有任何选项。
    猜你喜欢
    • 2014-11-18
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    相关资源
    最近更新 更多