你如何在 Starman 服务器上使用 Plack::Middleware::Session?

How do you use Plack::Middleware::Session with a Starman Server?

我有一个基于 Starman 的服务器 -

#!/usr/bin/perl
use strict;
use warnings;
use Data::Printer;
use Plack::Builder;

my $app = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};

    # Print environment variables
    p($env);

    return [
        200,
        [ 'Content-Type' => 'text/plain' ],
        [ "Hello, you've been here for ", $session->{counter}++, "th   time!" ],
    ];
};

my $default = sub {
    my $env = shift;
    p($env);
    return [
        '200', [ 'Content-Type' => 'text/html' ],
        ["Welcome to default page"],
    ];
};

builder {
    mount "/validate" => builder {
        enable "Middleware::Authentication"
        enable "Session";
        $app;
    };
    mount "/" => builder { $default };
};

我自己的中间件"Authentication"验证用户和return用于会话管理的会话信息(到期时间,会话密钥等),那么我如何在会话中间件中使用这些信息?

如果我没理解错的话,你的问题只是中间件的顺序问题。在 Auth.

之前启用 Session

检查以下内容,使用文件存储,会话被持久存储。尝试一下,重新启动 Starman,计数器将重新加载。 (我使用 inline 中间件来替代您的 Authentication。)

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Printer;
use Plack::Builder;

my $app = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};
    return [
        200,
        [ 'Content-Type' => 'text/html' ],
        [
            "My app page is visited ",
            $session->{counter}++,
            "th times! Validation is done at:",
            $session->{mwaretime},
            q{<br><a href="/validate">go validate again</a> --- <a href="/">reload this page</a>}
        ],
    ];
};

my $validate = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};
    $session->{counter} = 0;
    return [
        '200', [ 'Content-Type' => 'text/html' ],
        [
            "Resetting the counter:",
            $session->{counter},
             ". Time from middleware: ",
            $session->{mwaretime},
            q{<br> <a href="/validate">reload this page</a> --- <a href="/">go to index</a> }
        ],
    ];
};

builder {
    #the session will be stored persistently
    #enable the Session BEFORE your middleware
    enable 'Session', store => 'File';

    mount "/validate" => builder {
        #enable "Authentication";
        #following is same as an middleware
        enable sub {
            my $app = shift;
            return sub {
                my $env = shift;
                my $session = $env->{'psgix.session'};
                $session->{mwaretime} = time();
                $app->($env);
            };
        };
        #end of the middleware
        $validate;
    };
    mount "/" => $app 
};

从你的问题来看,很难说出你的要求到底是什么样的。但是,如果您希望对会话管理有如此多的控制,那么编写您自己的中间件可能会更好。也就是说,有一些方法可以使 Plack::Middleware::Session 适应某些场景。但是他们中的大多数或多或少地使用了未记录的功能。这意味着您必须熟悉源代码,并且这些功能可能会在以后的版本中更改或消失。

如果您想提供自己的会话密钥,可以将自定义 SID 生成器和验证器传递给 Plack::Session::State:

enable 'Session',
    state => Plack::Session::State->new(
        sid_generator => $my_generator,
        sid_validator => $my_validator,
    );

sid_generatordocumentation基本上是对"just read the source"说的。

您还可以实施自己的 Plack::Session::Store 后端。但在这种情况下,切换到自定义解决方案可能更有意义。

关于 cookie 过期时间,您可以在 $env->{'psgix.session.options'} 中设置 expires 选项,然后 创建一个新的 cookie:

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

这不是超时,而是自 UNIX 纪元以来的秒数,或 Cookie::Baker 接受的任何值。

也许您应该重新考虑您的身份验证中间件是否真的必须生成会话密钥。就像@jm666 所说的那样,您通常 运行 身份验证之前的会话中间件。然后你的验证码就可以访问所有的会话信息了。会话 ID 通常是会话管理的一个实现细节,不必关心代码的其他部分。要更改到期时间,请参阅