I have code which works with apache 2.2 but not apache 2.4, and I have
boiled this down to a simple reproducing test case.
It works with: Ubuntu 12.04 (apache 2.2.22, mod_perl 2.0.5,
Apache2::AuthCookie 3.18)
It does not work with: Ubuntu 14.04 (apache 2.4.7, mod_perl 2.0.8,
Apache2::AuthCookie 3.20)
The second setup gives the following in the error log:
failed to resolve handler Example::AuthHandler
when trying to access a page under /testsite/protected/ *after* you have
successfully logged in. If you go to /testsite/logout.html to clear the
cookie, and then to /testsite/protected/<any>, it still displays the
login page successfully.
The test case is so small that I've reproduced it entirely inline below.
You can also get it as a 1.5KB tar bundle from
https://osl.uoregon.edu/redmine/attachments/download/155/authcookiesite.tgz
I see some fairly old reports here:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666837
https://rt.cpan.org/Public/Bug/Display.html?id=85832
however from the first link, it *looks* like all this should be working
with Debian (and hence Ubuntu 14.04 recently derived from it).
I notice that there is a newer version of Apache2::AuthCookie (3.22)
available, so I installed that from CPAN. But this changes the error to:
[Wed Jun 25 13:35:26.054231 2014] [perl:error] [pid 17668] [client
10.0.2.2:50801] Can't locate object method "requires" via package
"Apache2::RequestRec" at
/usr/local/share/perl/5.18.2/Apache2/AuthCookie.pm line 388.\n, referer:
http://localhost:8013/testsite/protected/example.html
and indeed, I see no 'requires' member in
http://perl.apache.org/docs/2.0/api/Apache2/RequestRec.html
Does anybody have any clues they can pass on?
Many thanks,
Brian Candler.
(Code assumes it's unpacked under /var/tmp; if it's somewhere else then
change the first line of testsite.conf and setup.pl as appropriate)
==> testsite.conf <==
PerlRequire /var/tmp/setup.pl
PerlModule Example::TestSite
PerlModule Example::AuthHandler
PerlSetVar TestAuthPath /testsite
PerlSetVar TestAuthLoginScript /testsite/login.html
<Location /testsite/>
### To recognize logged-in users even outside of protected area:
#AuthType Example::AuthHandler
#AuthName TestAuth
SetHandler perl-script
PerlResponseHandler Example::TestSite
</Location>
<Location /testsite/protected/>
AuthType Example::AuthHandler
AuthName TestAuth
PerlAuthenHandler Example::AuthHandler->authenticate
PerlAuthzHandler Example::AuthHandler->authorize
Require valid-user
</Location>
<Location /testsite/dologin>
AuthType Example::AuthHandler
AuthName TestAuth
PerlResponseHandler Example::AuthHandler->login
</Location>
<Location /testsite/logout.html>
AuthType Example::AuthHandler
AuthName TestAuth
</Location>
==> setup.pl <==
use lib qw(/var/tmp);
1;
==> Example/TestSite.pm <==
package Example::TestSite;
use strict;
use warnings;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => qw(OK);
use Example::AuthHandler ();
sub handler {
my $r = shift;
$r->content_type('text/html');
$r->status(200);
$r->print(<<EOS);
<html><body>
<p>
<a href="/testsite/general.html">General</a> |
<a href="/testsite/protected/example.html">Protected</a> |
<a href="/testsite/logout.html">Logout</a>
</p>
EOS
if ($r->uri() eq '/testsite/login.html') {
$r->print(<<EOS);
<p>Please login:</p>
<form action="/testsite/dologin" method="post">
<input type="text" name="credential_0" />
<input type="password" name="credential_1" />
<input type="hidden" name="destination"
value="/testsite/protected/success.html" />
<input type="submit" />
</form>
EOS
}
elsif ($r->uri() eq '/testsite/logout.html') {
$r->auth_type->logout($r);
$r->print("<p>You are logged out, goodbye</p>");
}
else {
$r->print("<p>Hello, uri is " . $r->uri() . "</p>\n"); # FIXME:
escape html
if ($r->user) {
$r->print("<p>You are logged in as " . $r->user . "</p>\n");
}
else {
Example::AuthHandler->recognize_user($r);
if ($r->user) {
$r->print("<p>(Not protected but I recognize you as ". $r->user
. ")</p>\n");
}
}
}
$r->print(<<EOS);
</body></html>
EOS
return Apache2::Const::OK;
}
1;
==> Example/AuthHandler.pm <==
package Example::AuthHandler;
use base qw(Apache2::AuthCookie);
sub authen_cred ($$\@) {
my $self = shift; # Package name (same as AuthName directive)
my $r = shift; # Apache request object
my @cred = @_; # Credentials from login form
if ($cred[0] eq 'foo' && $cred[1] eq 'bar') {
return 'abcd1234';
}
return undef;
}
sub authen_ses_key ($$$) {
my ($self, $r, $session_key) = @_;
if ($session_key eq 'abcd1234') {
return 'foo';
}
return undef;
}
1;