=cut
###----------------------------------------------------------------###
-# Copyright 2006 - Paul Seamons #
+# Copyright 2007 - Paul Seamons #
# Distributed under the Perl Artistic License without warranty #
###----------------------------------------------------------------###
use Digest::MD5 qw(md5_hex);
use CGI::Ex;
-$VERSION = '2.02';
+$VERSION = '2.12';
###----------------------------------------------------------------###
$self->key_time => $self->server_time,
$self->key_payload => $self->generate_payload({%$data, login_form => 1}),
$self->key_expires_min => $self->expires_min,
-
+ text_user => $self->text_user,
+ text_pass => $self->text_pass,
+ text_save => $self->text_save,
};
}
my $key;
for my $armor ('none', 'base64', 'blowfish') { # try with and without base64 encoding
my $copy = ($armor eq 'none') ? $token
- : ($armor eq 'base64') ? decode_base64($token)
+ : ($armor eq 'base64') ? eval { local $^W; decode_base64($token) }
: ($key = $self->use_blowfish) ? decrypt_blowfish($token, $key)
: next;
if ($copy =~ m|^ ([^/]+) / (\d+) / (-?\d+) / (.*) / ([a-fA-F0-9]{32}) (?: / (sh\.\d+\.\d+))? $|x) {
} elsif (! defined($pass = eval { $self->get_pass_by_user($data->{'user'}) })) {
$data->add_data({details => $@});
$data->error('Could not get pass');
+ } elsif (ref $pass eq 'HASH') {
+ my $extra = $pass;
+ $pass = exists($extra->{'real_pass'}) ? delete($extra->{'real_pass'})
+ : exists($extra->{'password'}) ? delete($extra->{'password'})
+ : do { $data->error('Data returned by get_pass_by_user did not contain real_pass or password'); undef };
+ $data->error('Invalid login') if ! defined $pass && ! $data->error;
+ $data->add_data($extra);
}
return $data if $data->error;
if ( (defined($data->{'use_plaintext'}) ? $data->{'use_plaintext'} : $self->use_plaintext) # ->use_plaintext is true if ->use_crypt is
|| (defined($data->{'use_crypt'}) && $data->{'use_crypt'})
|| (defined($data->{'type'}) && $data->{'type'} eq 'crypt')) {
- $token = $data->{'user'} .'/'. $data->{'real_pass'};
+ my $pass = defined($data->{'test_pass'}) ? $data->{'test_pass'} : $data->{'real_pass'};
+ $token = $data->{'user'} .'/'. $pass;
### all other types go to cram - secure_hash_cram, cram, plaintext and md5
} else {
<input type="hidden" name="[% key_expires_min %]" value="">
<table class="login_table">
<tr class="login_username">
- <td>Username:</td>
+ <td>[% text_user %]</td>
<td><input name="[% key_user %]" type="text" size="30" value=""></td>
</tr>
<tr class="login_password">
- <td>Password:</td>
+ <td>[% text_pass %]</td>
<td><input name="[% key_pass %]" type="password" size="30" value=""></td>
</tr>
<tr class="login_save">
<td colspan="2">
- <input type="checkbox" name="[% key_save %]" value="1"> Save Password ?
+ <input type="checkbox" name="[% key_save %]" value="1"> [% text_save %]
</td>
</tr>
<tr class="login_submit">
};
}
+sub text_user { my $self = shift; return defined($self->{'text_user'}) ? $self->{'text_user'} : 'Username:' }
+sub text_pass { my $self = shift; return defined($self->{'text_pass'}) ? $self->{'text_pass'} : 'Password:' }
+sub text_save { my $self = shift; return defined($self->{'text_save'}) ? $self->{'text_save'} : 'Save Password ?' }
+
sub login_script {
return q {
[%~ IF ! use_plaintext %]
=head1 SYNOPSIS
- ### authorize the user
- my $auth = $self->get_valid_auth({
- get_pass_by_user => \&get_pass_by_user,
- });
+ use CGI::Ex::Auth;
+ ### authorize the user
+ my $auth = CGI::Ex::Auth->get_valid_auth({
+ get_pass_by_user => \&get_pass_by_user,
+ });
- sub get_pass_by_user {
- my $auth = shift;
- my $user = shift;
- my $pass = some_way_of_getting_password($user);
- return $pass;
- }
+
+ sub get_pass_by_user {
+ my $auth = shift;
+ my $user = shift;
+ my $pass = some_way_of_getting_password($user);
+ return $pass;
+ }
+
+ ### OR - if you are using a OO based CGI or Application
+
+ sub require_authentication {
+ my $self = shift;
+
+ return $self->{'auth'} = CGI::Ex::Auth->get_valid_auth({
+ get_pass_by_user => sub {
+ my ($auth, $user) = @_;
+ return $self->get_pass($user);
+ },
+ });
+ }
+
+ sub get_pass {
+ my ($self, $user) = @_;
+ return $self->loopup_and_cache_pass($user);
+ }
=head1 DESCRIPTION
secure_hash_keys
template_args
template_include_path
+ text_user
+ text_pass
+ text_save
use_base64
use_blowfish
use_crypt
$self->key_time # $self->server_time, # the server's time
$self->key_payload # $data->{'payload'} # the payload (if any)
$self->key_expires_min # $self->expires_min # how many minutes crams are valid
+ text_user # $self->text_user # template text Username:
+ text_pass # $self->text_pass # template text Password:
+ text_save # $self->text_save # template text Save Password ?
=item C<key_logout>
enabled, it should return the crypted password. If use_plaintext and use_crypt
are not enabled, it may return the md5 sum of the password.
+ get_pass_by_user => sub {
+ my ($auth_obj, $user) = @_;
+ my $pass = $some_obj->get_pass({user => $user});
+ return $pass;
+ }
+
+Alternately, get_pass_by_user may return a hashref of data items that
+will be added to the data object if the token is valid. The hashref
+must also contain a key named real_pass or password that contains the
+password. Note that keys passed back in the hashref that are already
+in the data object will override those in the data object.
+
+ get_pass_by_user => sub {
+ my ($auth_obj, $user) = @_;
+ my ($pass, $user_id) = $some_obj->get_pass({user => $user});
+ return {
+ password => $pass,
+ user_id => $user_id,
+ };
+ }
+
=item C<cgix>
Returns a CGI::Ex object.
is capable of taking the login_fields and creating an md5 cram which prevents
the password from being passed plaintext.
+=item C<text_user, text_pass, text_save>
+
+The text items shown in the default login template. The default values are:
+
+ text_user "Username:"
+ text_pass "Password:"
+ text_save "Save Password ?"
+
+=back
+
=head1 AUTHORS
-Paul Seamons <perlspam at seamons dot com>
+Paul Seamons <paul at seamons dot com>
=cut