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

发布于 2024-08-17 13:39:35 字数 2840 浏览 2 评论 0原文

使用 CGI::Session:: 中的示例Auth::DBICGI::Session ::Auth页面,我尝试实现_login功能但没有成功。我使用的是 Windows 7 和 Apache 2。

#!/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>";
}

渲染的输出是:

login ok
not logged in

如果我将传递给 _login 的值更改为“foo”、“bar”(无效的用户名/密码),那么我得到这个渲染结果:

login fail
not logged in

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

文档说 _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');

话又说回来,如果 _login 返回 true 并带有有效的用户名和密码,那么我会假设该用户 ID 是有效的...不是吗?

更新 4:

我还在我们的 Linux 生产服务器上对此进行了测试,并且遇到了完全相同的问题。

Using the examples from the CGI::Session::Auth::DBI and CGI::Session::Auth pages, I have attempted to implement the _login function with no success. I'm using Windows 7 and Apache 2.

#!/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>";
}

The rendered output from this is:

login ok
not logged in

If I change the values passed to _login to "foo", "bar" (an invalid username/password), then I get this rendered result:

login fail
not logged in

I'm using '.' just for testing as I know it's a dir I can write to. Every time I run the code, a cgisess_ file is created (e.g. cgisess_9fb493cc9155ee9dd2b18fddc38139d8), but this is created regardless of if I use a correct username or not. No errors are being returned, but $auth->loggedIn is always false.

The documentation says that _login is virtual, and it sounds like the DBI module overrides this, but I'm not sure.

What could I be doing wrong?

Update 1:

I've also tried using $auth->authenticate() before the call to $auth->loggedIn but this has no effect. I've also tried using $auth->authenticate() and $auth->loggedIn on another after successful login, but I get the same result. No matter what I do, $auth->loggedI is always false.

Update 2:

I've also tried chaning the directory to "/" and all it does is create the cgisess files in / rather than current dir.

Update 3:

I figured it may be an issue with the database records; I'm using the default example ones from the example page, but with a modified admin password. Here's a phpMyAdmin export:

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');

Then again, if _login is returning true with a valid username and password, then I would assume that the userid is valid... No?

Update 4:

I've also tested this on our Linux production server, and I get the exact same issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青巷忧颜 2024-08-24 13:39:35

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

另外,_login()仅执行与数据库的身份验证,但不会修改$auth对象。使用 authenticate() 时,您需要使用 $cgi 对象的 param() 函数定义用户名和密码。您需要设置字段 log_usernamelog_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>";
}

我还没有测试过,但这应该有效。

Try outputting the results of $session->header() as the first thing you output. This should set your cookie and load the existing session instead of creating a new one each time.

Also, _login() only performs the authentication with the database, but does not modify the $auth object. Using authenticate(), you need to define the username and password using the param() function of your $cgi object. You need to set the fields log_username and log_password for the authenticate() function to work.

#!/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>";
}

I haven't tested it, but this should be working.

童话 2024-08-24 13:39:35

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

_登录()

这个虚拟方法执行
通过比较实际登录尝试
访问者发送的登录表单数据
一些本地用户数据库。 _login
基类的方法
CGI::Session::Auth 只知道用户
“guest”,密码为“guest”。

要访问真实的用户数据库,您
必须使用修改的子类
适当地使用 _login 方法。看
Auth/ 子目录中的模块。

The doc is pretty clear that you have to override the _login() method, unless guest/guest works for you. Plus you aren't calling authenticate(), which actually invokes _login(), you shouldn't be doing it.

_login()

This virtual method performs the
actual login attempt by comparing the
login form data the visitor sent with
some local user database. The _login
method of the base class
CGI::Session::Auth only knows the user
'guest' with password 'guest'.

To access a real user database, you
have to use a subclass that modifies
the _login method appropriately. See
the modules in the Auth/ subdirectory.

深者入戏 2024-08-24 13:39:35

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

LoginVarPrefix:默认情况下,CGI::Session::Auth 期望访问者的用户名和密码以表单变量“log_username”和“log_password”的形式传递。为了避免冲突,可以通过此参数更改前缀“log_”。

我相信这会起作用

$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>";
}

Looking at the source code and documentation, _login() never actually sets the internal loggedin flag. That is only performed in the authenticate module. You should also remember that it is generally accepted perl practice that methods starting with '_' should be treated essentially as private methods, (or in Java terminology perhaps protected) only to be used by subclasses. So you shouldn't be using _login directly.

LoginVarPrefix: By default, CGI::Session::Auth expects the username and password of the visitor to be passed in the form variables 'log_username' and 'log_password'. To avoid conflicts, the prefix 'log_' can be altered by this parameter.

I believe this will work

$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>";
}
梦太阳 2024-08-24 13:39:35

您可以通过将其放在 my $cgi = new CGI; 之上来打开日志记录这

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

将打开调试并让您了解更多正在发生的事情。

You can turn on logging by putting this above the my $cgi = new CGI; line

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

This will turn on debugging and allow you to see more of what is going on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文