我有一个基于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 };
};
我自己的中间件"身份验证"对用户进行身份验证,并返回会话信息(到期时间、会话密钥等)用于会话管理,那么我如何在会话中间件中利用这些信息呢?
如果我理解正确,您的问题只是中间件的顺序。在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_generator
的文档基本上说"只需阅读源代码"。
您还可以实现自己的Plack::Session::Store
后端。但在这种情况下,切换到自定义解决方案可能更有意义。
关于cookie过期时间,您可以在创建新cookie之前在$env->{'psgix.session.options'}
中设置expires
选项:
$env->{'psgix.session.options'}{expires} = $my_expires;
这不是超时,而是自UNIX epoch或Cookie::Baker
接受的任何值以来的时间(以秒为单位)。
也许您应该重新考虑您的身份验证中间件是否真的必须生成会话密钥。正如@jm666所说,您通常在身份验证之前运行会话中间件。然后,您的身份验证码可以访问所有会话信息。会话ID通常是会话管理的实现细节,不必涉及代码的其他部分。要更改过期时间,请参阅我对此问题的回答。