Here's a simple handler that will set the AuthType and AuthName
dynamically and handle the authentication for you. This handler will
prompt you for a password when you try to acess /manual with the
AuthName, "The Manual" and prompt with the AuthName "The Icons" when you
try to access /icons. These urls are part of Apaches basic installation
(that's if you did not remove the manual from your htdocs directory).
The authentication phase will let you in just as long you supply a
username and password. You can of course code such that it you can
authenicate against a .htpassword file, using Apache::Htpasswd.
Anyhow, this should show you that you can indeed change the AuthName
on-the-fly and also handle
authentication without having to include AuthName,AuthType,AuthUserFile
explicitly in your httpd.conf.
Note: the authentication subroutine acted flaky, sometimes it worked and
other times it didn't. But the realms did change for the each uri.
i hope this helps you....have fun ;)
Setting it up:
In your httpd.conf ( in a global area):
PerlHeaderParserHandler Apache::SetRealm;
=code
package Apache::SetRealm;
use Apache;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
## Make Apache aware the we want to also handle the Authentication
phase using a custom
## handler, in this case the subroutine authenticate()
$r->push_handlers(PerlAuthenHandler => \&authenticate);
my $uri = $r->uri;
## only handle uri that are defined as protected, in this case the
only protected
## uri's are /icons and /manuals
return OK unless is_protected($r);
my $realm = get_realm($r);
## Construct the Header Field containing the type of authenticate
(Basic) and our
## realmname return by get_realm()
my $authheader = 'Basic realm="'.$realm.'"';
$r->header_out("WWW-Authenticate" ,$authheader);
## Return 401 to browser and prompt for login
$r->status(AUTH_REQUIRED);
$r->send_http_header("text/html");
return AUTH_REQUIRED;
}
sub get_realm {
## Get the AuthName for a specific uri. You can probably read these
off of a file that
## contains a list of uri's and realmNames
my $r = shift;
return "The Icons" if ($r->uri =~ /\/icons/);
return "The Manual" if ($r->uri =~ /\/manual/);
}
sub is_protected {
## Check the $uri requested matches our set of "Restricted"
locations
## 1 = isProtected, 0 = NotProtected
## You can probably have these protected areas in a seperate file,
the eagle book
## has some excellent ideas on how to acomplish this
my $r = shift;
my @protected = ('\/manual','\/icons');
for (@protected) { return 1 if ($r->uri =~ /$_/); }
return 0;
}
sub authenticate {
## Straight out of the Eagle Book
my $r = shift;
return OK if $r->sub_request;
my ($res,$password) = $r->get_basic_auth_pw;
return $res if $res != OK;
my $username = $r->connection->user;
unless ($username && $pass) {
$r->note_basic_auth_failure;
$r->log_reason("Did not provide username");
return AUTH_REQUIRED;
}
## Now that you have the $username and $password you can
## include your code to open your AuthUserFile to check the password
and username
## I suggest using Apache::Htpasswd, it provides all the
methods/functions that you need to
## accomplish this part of the task...
$r->log_reason("WELCOME $user");
return OK;
}
1;
-Carlos
Todd Chapman wrote:
>
> Please explain again how to get my AuthHandler called without setting
> AuthName or AuthType in httpd.conf.
>
> Thanks.
>
> -Todd
>
> On Wed, 27 Sep 2000, Carlos Ramirez wrote:
>
> > By choosing to use your custom AuthHandler, you basically override Apache's way of
> > handling the particular phase, in this case the authentication phase. So you must
> > handle prompting the user and also checking the password.
> >
> > You might want to read the Apache Guide (http://perl.apache.org/) on how to write
>you
> > own handler and also the eagle book.
> >
> > After reviewing our previous conversation, I think you might need to send
> > WWW-Authenticate header field in another phase (preferable at the
> > PerlHeaderParserHandler) before the Authentication phase is called.
> >
> > Your PerlHeaderParserHandler can check the $r->uri for any password protected
> > requests, i.e., if it matches /companyA, you can then set the WWW-Authenticate:
>Basic
> > $realm and push it along it's merry way.
> >
> > Then your PerlAuthHandler will get the username and password and check it against
>the
> > realms' AuthUserFile. Apache will handle the initial prompting for the
> > username/password.
> >
> > Your requirements imply that you will have a file(??) that has a list of UserFiles
> > for each Realm/path_info so that your authentication handler will know what file to
> > check against.
> >
> > I hope this make sense ;) my coffee is running low...
> >
> > -Carlos
> >
> >
> > Todd Chapman wrote:
> >
> > > Thanks for the help. I was hoping that Apache would check the password for
> > > me but this should work.
> > >
> > > Now, how do I get Apache to run my PerlAuthenHandler without setting the
> > > AuthType or AuthName in httpd.conf?
> > >
> > > Do I need to do the Authentication in a PerlHandler?
> > >
> > > -Todd
> > >
> > > On Wed, 27 Sep 2000, Carlos Ramirez wrote:
> > >
> > > > 1. Oh, I mis-interpreted your question. I thought you already had a list of
> > > > virtual directories with the
> > > > AuthNames defined.
> > > >
> > > > You can set the AuthName by sending them in the server response header field:
> > > >
> > > > WWW-Authenticate Basic $realm
> > > >
> > > > So the first request to /companyA, you AuthHandler will respond with:
> > > >
> > > > $r->header_out(WWW-Authenticate => 'Basic $realm); ## Sets Realm field
> > > > $r->note_basic_auth_failure; ## Prompts for password
> > > >
> > > > The when a username and password are supplied i.e.
> > > > ($ret,$password) = $r->get_basic_auth_pw;
> > > >
> > > > where $ret = 1;
> > > >
> > > > Then:
> > > > 1. determine the AuthUserFile
> > > > 2. use Apache::Htpasswd to check password
> > > >
> > > > -Carlos
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > Todd Chapman wrote:
> > > >
> > > > > Problems with your suggestion:
> > > > >
> > > > > 1. The realm will not be known until I get path_info so
> > > > > <Location></Location> directives will not work.
> > > > >
> > > > > 2. How can I get Perl to do the password lookup in the dynamically
> > > > > selected AuthUserFile?
> > > > >
> > > > > Thanks for the help.
> > > > >
> > > > > -Todd
> > > > >
> > > > > On Wed, 27 Sep 2000, Carlos Ramirez wrote:
> > > > >
> > > > > > You can you use Location to specify seperate AuthUserFile's like so:
> > > > > >
> > > > > > <Location /companyA>
> > > > > > AuthType Basic
> > > > > > AuthName CompanyA
> > > > > > AuthUserFile path/to/CompanyAUsersFile
> > > > > >
> > > > > > </Location>
> > > > > > ....
> > > > > > <Location /companyN>
> > > > > > AuthType Basic
> > > > > > AuthName CompanyN
> > > > > > AuthUserFile path/to/CompanyNUsersFIle
> > > > > > </Location>
> > > > > >
> > > > > >
> > > > > > Or you can write your own AuthHandler that lookups up AuthName,
>AuthUserFile
> > > > > > in a seperate file against the path_info. This will eliminate the need to
> > > > > > flood you httpd.conf file with a bunch of <Location></Location> directives.
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > Todd Chapman wrote:
> > > > > >
> > > > > > > I have read chapter 6 of the modperl book but still don't know how to set
> > > > > > > up authenification the way I want. I would like to use Basic
> > > > > > > authentification to protect virtual documents. The trick is that I want
> > > > > > > to set AuthName and AuthUserFile based on path_info.
> > > > > > >
> > > > > > > For example:
> > > > > > >
> > > > > > > http://virtual/companyA/dir1
> > > > > > >
> > > > > > > would prompt for a password in the companyA realm and check it against
>the
> > > > > > > appropriate AuthUserFile.
> > > > > > >
> > > > > > > How do I add this flexibility without reinventing the parts Apache
>already
> > > > > > > does so well?
> > > > > > >
> > > > > > > Thanks.
> > > > > > >
> > > > > > > -Todd
> > > > > >
> > > > > > --
> > > > > > -----------------------------------------------------------------------
> > > > > > Carlos Ramirez + Boeing + Reusable Space Systems + 714.372.4181
> > > > > > -----------------------------------------------------------------------
> > > > > > - Someday I'll find that peer and reset his connection!
> > > > > >
> > > > > >
> > > > > >
> > > >
> > > > --
> > > > -----------------------------------------------------------------------
> > > > Carlos Ramirez + Boeing + Reusable Space Systems + 714.372.4181
> > > > -----------------------------------------------------------------------
> > > > - Someday I'll find that peer and reset his connection!
> > > >
> > > >
> > > >
> >
> > --
> > -----------------------------------------------------------------------
> > Carlos Ramirez + Boeing + Reusable Space Systems + 714.372.4181
> > -----------------------------------------------------------------------
> > - Someday I'll find that peer and reset his connection!
> >
> >
> >
--
Claiming that your operating system is the best in the world because
more people use it is like saying
McDonalds makes the best food in the world.