【发布时间】:2012-09-04 17:02:39
【问题描述】:
这是我的身份验证逻辑:
sub user_logon {
my ($dbh, $cgi, $cache, $logout) = @_;
#use Log::Log4perl qw(:easy);
#Log::Log4perl->easy_init($DEBUG);
my $session = new CGI::Session("driver:MySQL", $cgi, {Handle=>$dbh});
$session->expires("+3h");
my $auth = new CGI::Session::Auth::DBI({
CGI => $cgi,
Session => $session,
IPAuth => 1,
DBHandle => $dbh,
#Log => 1,
});
if($logout) {
$auth->logout();
}
else {
$auth->authenticate();
if($auth->loggedIn) {
my $user = Cherry::Schema::ResultSet::Employee::get_employee($dbh, $cache, { number => $auth->{userid} });
if (!$user->{active}) {
return { error => $user->{name} . ' is not an active employee.' };
}
$user->{cookie} = $auth->sessionCookie();
return $user;
}
elsif($cgi->param('action') eq 'logon') {
if($cgi->param('log_username') && $cgi->param('log_username')) {
return { error => 'Your username and/or password did not match.' };
}
elsif(!$cgi->param('log_username') || !$cgi->param('log_username')) {
return { error => 'Please enter a username and a password.' };
}
}
else {
return { error => 'You are not logged in' };
}
}
}
sub handle_authentication {
my ($dbh, $cache, $config, $params, $cgi) = @_;
if(($cgi->param('auth') || '') eq 'super_user') { # for automation
return;
}
if(($params->{action} || '') eq 'log_off') {
user_logon($dbh, $cgi, $cache, 1); # 1 means log out
login_form($config, 'Successfully logged out', $params->{login_url}, $params->{title});
}
my $user = user_logon($dbh, $cgi, $cache);
if(exists $user->{error}) {
login_form($config, $user->{error}, $params->{login_url}, $params->{title});
}
elsif($user->{number}) {
return $user;
}
}
然后在我的代码中,每次打印标题时,它看起来像这样:
my $user = Cherry::Authentication::handle_authentication(
$dbh,
$cache,
\%config,
{
action => $FORM{action},
username => $FORM{log_username},
password => $FORM{log_password},
auth => $FORM{auth}
},
$cgi
);
print header(
-type => 'application/json',
-cookie => $user->{cookie}
);
问题是这段代码似乎在大约 80% 的时间里运行良好。另外 20% 的用户会被踢出(而不是在陈旧 3 小时后)。
这段代码有什么明显的缺陷吗?我是否遗漏了任何关键代码?
如果您觉得这里没有足够的信息来提供可行的解决方案,您对如何解决这些类型的问题有任何一般性建议吗?
【问题讨论】:
-
你能看看用户发送的标题吗?也许cookie正在消失。另外,是否涉及多个数据库服务器?我在一个 web 服务器集群中看到了这一点,其中会话文件进入本地文件系统而不是共享文件系统,但是你没有文件,你有一个 db。可能会发生类似的事情。它发生在所有用户身上还是仅仅发生在一些用户身上?他们的特点是什么?你能找到共同的标识符来对它们进行分组吗?我会先看看文件/会话。留意桌子,寻找同一用户何时进行第二次会话。
-
我同意 simbabque 的说法。使用当前信息,我会说添加更多日志记录。如果注销功能被触发,您应该记录,何时,由谁等。