我有一个Mojolicious应用程序和一个用于身份验证的桥梁。这是我的情景:
我在数据库中有一组标准错误响应,我通过传递一个值来查询,比如返回一个带有详细错误响应的404。数据库将具有与错误相对应的共同细节,而其他用户特定细节(例如ip和用户名)是从控制器获得的。请查看有关如何构建错误响应的this link。
我有一个帮助器,它获取控制器的实例和错误代码,以生成所需的响应。我使用控制器对象通过包含错误响应的表的结果集来查询db。通过控制器,我还可以获得创建响应所需的用户特定详细信息。然后创建响应,发送回控制器,然后作为Json返回。
我的问题是注销,我设置$self->session(expires => 1)
使会话无效。在尝试再次注销时,我使用控制器访问帮助程序构建错误响应并将其发送到客户端。现在,任何尝试访问任何URI的尝试都会因以下检查的第一次尝试而无效。
unless($self->session('user')) {
my $res = Controller::Helper->error_res($self, 403);
$self->render_json($res, status => $res->{httpstatuscode});
return;
}
此检查首次运行,但是当我尝试再次访问资源(任意次数)时,此检查失败,并且无需登录即可访问资源。当我查看cookie时,会创建一个新的cookie。我在哪里错了?处理此类问题的最佳方法是什么? 辅助函数看起来像这样
error_res{
my($self,$c,$res) = @_;
my @arref = $c->db->resultset('Errorcode')->select_row($res);
my $ref=$arref[0];
$ref->{user}=$c->session->{user}->{name};
$ref->{request}=$c->req->method."".join("\\",$c->req->url->path);
$ref->{time}=scalar localtime();
return $ref;
}
其中res
是数据库中的id,用于标识特定错误。
那么,它是否与助手中仍然可用的控制器的引用有关?当我在帮助器中取消$c
时,它没有帮助。
编辑1:我在这里错过了一些观点,这是正确的方法吗?
编辑2:我在退出时使用户无效。当用户再次尝试注销时,我返回一个错误,其中包含有关错误的其他信息。但在创建有关错误的其他信息时,会创建一个没有用户信息的新会话。如果我执行以下操作,则不会发生这种情况
unless($self->session('user')) {
$self->render_json("message:User has not logged in", status => 403);
return;
}
答案 0 :(得分:3)
所以我想出了答案,奇怪的行为应该是perl的autovivification功能。它涉及动态创建数据结构。在我的情况下,我尝试通过
的会话cookie获取用户的名称$ref->{user}=$c->session->{user}->{name};
当用户未登录时,会话中未设置user
密钥,但在创建错误响应时,我尝试通过此密钥获取name
。这导致user
的创建没有任何价值。检查user
密钥是否存在可以解决问题。
答案 1 :(得分:1)
阅读完评论后,我更确定框架的行为符合预期。可能需要更改应用程序逻辑(如编辑2中所示)。
原因是,会话只是一个hashref,序列化为JSON,签名并存储在cookie中。如果你创建了密钥,那么它就在那里。我不知道还能告诉你什么。
是的,在前一个会话cookie到期后立即创建一个新的会话cookie。这对于框架是必要的,并且是完全预期的。