Perl 为什么$auth->;loggedIn在我使用CGI::Session::Auth::DBI时从来都不是真的?

Perl 为什么$auth->;loggedIn在我使用CGI::Session::Auth::DBI时从来都不是真的?,perl,authentication,cgi,Perl,Authentication,Cgi,使用和页面中的示例,我尝试实现\u login功能,但没有成功。我正在使用Windows7和Apache2 #!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); use CGI; use CGI::Session; use CGI::Session::Auth::DBI; my $cgi = new CGI; # using '.' directory for testing my $session = new

使用和页面中的示例,我尝试实现
\u login
功能,但没有成功。我正在使用Windows7和Apache2

#!/usr/bin/perl -w
use strict;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use CGI::Session;
use CGI::Session::Auth::DBI;

my $cgi = new CGI;

# using '.' directory for testing
my $session = new CGI::Session(undef, $cgi, {Directory=>'.'});
my $auth = new CGI::Session::Auth::DBI({
    CGI => $cgi,
    Session => $session,
    DSN => 'dbi:mysql:dbname=foobar:host=localhost',
    DBUser => 'foo',
    DBPasswd => 'bar',
    UserTable => 'cgi_auth_user' # auth_user already in use
});

print "Content-type: text/html\n\n";

if ($auth->_login("admin", "admin")) {
    print "<p>login ok</p>";
} else {
    print "<p>login fail</p>";
}

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}
如果我将传递给
\u login
的值更改为“foo”,“bar”(无效的用户名/密码),则会得到以下呈现结果:

login fail
not logged in
我使用“.”只是为了测试,因为我知道它是一个我可以写入的目录。每次我运行代码时,都会创建一个
cgisess_u
文件(例如
cgisess_9fb493cc9155ee9dd2b18fddc38139d8
),但无论我是否使用正确的用户名,都会创建该文件。没有返回错误,但
$auth->loggedIn
始终为false

文档中说,
\u login
是虚拟的,听起来好像DBI模块覆盖了这一点,但我不确定

我可能做错了什么

更新1: 在调用
$auth->loggedIn
之前,我也尝试过使用
$auth->authenticate()
,但没有效果。在成功登录后,我还尝试在另一台计算机上使用
$auth->authenticate()
$auth->loggedIn
,但得到了相同的结果。无论我做什么,
$auth->loggedI
总是错误的

更新2: 我还尝试将目录更改为“/”,它所做的只是在
/
中创建
cgisess
文件,而不是当前目录

更新3: 我想这可能是数据库记录的问题;我使用的是示例页面中的默认示例,但带有修改的管理员密码。这是phpMyAdmin导出:

CREATE TABLE IF NOT EXISTS `cgi_auth_user` (
  `userid` char(32) collate utf8_unicode_ci NOT NULL,
  `username` varchar(30) collate utf8_unicode_ci NOT NULL,
  `passwd` varchar(30) collate utf8_unicode_ci NOT NULL default '',
  PRIMARY KEY  (`userid`),
  UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `cgi_auth_user` (`userid`, `username`, `passwd`) VALUES
('325684ec1b028eaf562dd484c5607a65', 'admin', 'admin'),
('ef19a80d627b5c48728d388c11900f3f', 'guest', 'guest');
然后,如果
\u login
使用有效的用户名和密码返回
true
,那么我将假定该用户名是有效的。。。没有

更新4:
我也在我们的Linux生产服务器上对此进行了测试,我得到了完全相同的问题。

文档非常清楚,除非guest/guest适合您,否则您必须重写_login()方法。另外,您不应该调用authenticate(),它实际上调用了_login(),您不应该这样做

_登录()

此虚拟方法执行以下操作: 通过比较 访问者发送的登录表单数据 一些本地用户数据库。登录 基类的方法 CGI::Session::Auth只知道用户 密码为“guest”的“guest”

要访问真实用户数据库,您需要 必须使用修改 正确地使用_登录方法。看见 Auth/子目录中的模块


查看源代码和文档,
\u login()
从未实际设置内部
loggedin
标志。这仅在身份验证模块中执行。您还应该记住,perl中普遍接受的做法是,以“\u1”开头的方法基本上应被视为私有方法(或者用Java术语来说,可能是受保护的),只供子类使用。所以你不应该直接使用登录

LoginVarPrefix:默认情况下,CGI::Session::Auth希望以变量“log\u username”和“log\u password”的形式传递访问者的用户名和密码。为避免冲突,可通过此参数更改前缀“log_u2;”

我相信这会奏效

$session->param('log_username', 'admin');
$session->param('log_password', 'admin');

$auth->authenticate(); # no return value to check

print "Content-type: text/html\n\n";

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}
$session->param('log_username','admin');
$session->param('log_password','admin');
$auth->authenticate();#没有要检查的返回值
打印“内容类型:text/html\n\n”;
如果($auth->loggedIn){
打印“已登录;转到”

”; }否则{ 打印“未登录”

”; }
您可以通过将其置于my$cgi=新cgi上方来打开日志记录;线

use Log::Log4perl qw(:easy);
# Set priority of root logger to DEBUG
Log::Log4perl->easy_init($DEBUG);

这将打开调试并允许您查看更多正在进行的操作。

尝试将
$session->header()
的结果作为第一件输出。这应该设置cookie并加载现有会话,而不是每次创建一个新会话

另外,
\u login()
仅对数据库执行身份验证,但不修改
$auth
对象。使用
authenticate()
,您需要使用
$cgi
对象的
param()
函数定义用户名和密码。您需要设置字段
log\u username
log\u password
,以使
authenticate()
功能正常工作

#!/usr/bin/perl -w
use strict;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use CGI::Session;
use CGI::Session::Auth::DBI;

my $cgi = CGI->new;
my $session = new CGI::Session(undef, $cgi, {Directory=>'/tmp'});

my $auth = new CGI::Session::Auth::DBI({
    CGI => $cgi,
    Session => $session,
    DSN => 'dbi:mysql:dbname=foobar:host=localhost',
    DBUser => 'foo',
    DBPasswd => 'bar',
    UserTable => 'cgi_auth_user'
});

print $session->header();

$cgi->param('log_username', 'admin');
$cgi->param('log_password', 'admin');

$auth->authenticate();

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}
#/usr/bin/perl-w
严格使用;
使用CGI::Carp qw(fatalsToBrowser);
使用CGI;
使用CGI::Session;
使用CGI::Session::Auth::DBI;
my$cgi=cgi->新建;
my$session=new CGI::session(undf,$CGI,{Directory=>'/tmp'});
my$auth=new CGI::Session::auth::DBI({
CGI=>$CGI,
会话=>$Session,
DSN=>'dbi:mysql:dbname=foobar:host=localhost',
DBUser=>foo',
DBPasswd=>bar',
UserTable=>'cgi\U auth\U user'
});
打印$session->header();
$cgi->param('log_username','admin');
$cgi->param('log_password','admin');
$auth->authenticate();
如果($auth->loggedIn){
打印“已登录;转到”

”; }否则{ 打印“未登录”

”; }

我还没有测试过它,但它应该可以工作。

避免使用间接对象表示法(即
新CGI
)。使用方法调用语法(即
CGI->new
)。请参阅,我只是查看了代码,并且::DBI模块覆盖了_登录。至于你的代码不起作用的原因:数据库设置好了吗?你查过错误日志了吗?你能打开调试吗?是的,数据库已经设置好并开始工作;为了证明这一点,我改为一个错误的DB用户名,并得到了一个DB错误。我应该使用
perl
开关打开调试信息吗?我查看了
--help
,但不了解调试部分;也许这应该是一个新问题?$auth->Log=1(通过阅读源代码),您可以尝试使用Perl调试器运行它-我个人觉得有点困惑。我想如果您可以从命令行运行CGI脚本,这是一个可行的选择。虽然Auth模块有内置的调试语句,但请查看源代码。如麦戈锡
#!/usr/bin/perl -w
use strict;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use CGI::Session;
use CGI::Session::Auth::DBI;

my $cgi = CGI->new;
my $session = new CGI::Session(undef, $cgi, {Directory=>'/tmp'});

my $auth = new CGI::Session::Auth::DBI({
    CGI => $cgi,
    Session => $session,
    DSN => 'dbi:mysql:dbname=foobar:host=localhost',
    DBUser => 'foo',
    DBPasswd => 'bar',
    UserTable => 'cgi_auth_user'
});

print $session->header();

$cgi->param('log_username', 'admin');
$cgi->param('log_password', 'admin');

$auth->authenticate();

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}