0

これが私の認証ロジックです:

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 時間経過した後ではありません)。

このコードに明らかな欠陥はありますか? 重要なコードを除外しましたか?

実行可能な解決策を提供するのに十分な情報がここにないと思われる場合は、これらの種類の問題をトラブルシューティングするために何ができるかについて、一般的な提案はありますか?

4

1 に答える 1

0

この特定の問題で、私が気づかなかったいくつかのコードが機能していました。

$cookie = CGI::Cookie->new(
    -name       => $session->name, # problem line
    -value      => $session->id,   # problem line
    -expires    => '+1y',
    -path       => '/',
    -secure     => 0,
);

my @header = (
    -cookie => $cookie,
    -type => 'text/html',
    -status     => $status
);

print $cgi->header( @header );

コメント#problem行のある行は、セッションがすでに存在する場合でも、新しいセッションを割り当てていました。

最も問題が発生していると思われるユーザーのコンピューターにFiddlerHTTPDebuggerをインストールしました。次に、ユーザーが予期せずログアウトした後、ログを確認しました。1つのURLにアクセスしたユーザーと、次のリクエストで予期しないログアウトとの間に相関関係を見つけることができました。

于 2012-09-06T19:20:25.230 に答える