From c90b4dcd8d8ee9f3e80c0b81bb5fc792ae4c9d03 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Mon, 28 Feb 2011 10:10:15 +0100 Subject: [PATCH] Methoden zum Speichern von eindeutigen Keys in der Session MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Außerdem: Form dumpen und wiederherstellen; Werte nur für einen bestimmten Zeitraum speichern. --- SL/Auth.pm | 197 ++++++++++++++++++++++++++++++++++++++++++++--- SL/Dispatcher.pm | 2 +- 2 files changed, 188 insertions(+), 11 deletions(-) diff --git a/SL/Auth.pm b/SL/Auth.pm index 62686a635..a2e98322f 100644 --- a/SL/Auth.pm +++ b/SL/Auth.pm @@ -487,7 +487,10 @@ sub restore_session { while (my $ref = $sth->fetchrow_hashref()) { $self->{SESSION}->{$ref->{sess_key}} = $ref->{sess_value}; - $form->{$ref->{sess_key}} = $self->_load_value($ref->{sess_value}) if (!defined $form->{$ref->{sess_key}}); + next if defined $form->{$ref->{sess_key}}; + + my $params = $self->_load_value($ref->{sess_value}); + $form->{$ref->{sess_key}} = $params->{data} if $params->{auto_restore} || $params->{simple}; } $sth->finish(); @@ -498,15 +501,26 @@ sub restore_session { } sub _load_value { - return $_[1] if $_[1] !~ m/^---/; + my ($self, $value) = @_; + + return { simple => 1, data => $value } if $value !~ m/^---/; - my $value; + my %params = ( simple => 1 ); eval { - $value = YAML::Load($_[1]); + my $data = YAML::Load($value); + + if (ref $data eq 'HASH') { + map { $params{$_} = $data->{$_} } keys %{ $data }; + $params{simple} = 0; + + } else { + $params{data} = $data; + } + 1; - } or return $_[1]; + } or $params{data} = $value; - return $value; + return \%params; } sub destroy_session { @@ -643,7 +657,7 @@ sub set_session_value { $self->{SESSION} ||= { }; while (my ($key, $value) = each %params) { - $self->{SESSION}->{ $key } = YAML::Dump($value); + $self->{SESSION}->{ $key } = YAML::Dump(ref($value) eq 'HASH' ? { data => $value } : $value); } $main::lxdebug->leave_sub(); @@ -667,12 +681,85 @@ sub delete_session_value { sub get_session_value { $main::lxdebug->enter_sub(); - my $self = shift; - my $value = $self->{SESSION} ? $self->_load_value($self->{SESSION}->{ $_[0] }) : undef; + my $self = shift; + my $params = $self->{SESSION} ? $self->_load_value($self->{SESSION}->{ $_[0] }) : {}; $main::lxdebug->leave_sub(); - return $value; + return $params->{data}; +} + +sub create_unique_sesion_value { + my ($self, $value, %params) = @_; + + $self->{SESSION} ||= { }; + + my @now = gettimeofday(); + my $key = "$$-" . ($now[0] * 1000000 + $now[1]) . "-"; + $self->{unique_counter} ||= 0; + + $self->{unique_counter}++ while exists $self->{SESSION}->{$key . $self->{unique_counter}}; + $self->{unique_counter}++; + + $value = { expiration => $params{expiration} ? ($now[0] + $params{expiration}) * 1000000 + $now[1] : undef, + no_auto => !$params{auto_restore}, + data => $value, + }; + + $self->{SESSION}->{$key . $self->{unique_counter}} = YAML::Dump($value); + + return $key . $self->{unique_counter}; +} + +sub save_form_in_session { + my ($self, %params) = @_; + + my $form = delete($params{form}) || $::form; + my $non_scalars = delete $params{non_scalars}; + my $data = {}; + + my %skip_keys = map { ( $_ => 1 ) } (qw(login password stylesheet version titlebar), @{ $params{skip_keys} || [] }); + + foreach my $key (grep { !$skip_keys{$_} } keys %{ $form }) { + $data->{$key} = $form->{$key} if !ref($form->{$key}) || $non_scalars; + } + + return $self->create_unique_sesion_value($data, %params); +} + +sub restore_form_from_session { + my ($self, $key, %params) = @_; + + my $data = $self->get_session_value($key); + return $self unless $data; + + my $form = delete($params{form}) || $::form; + my $clobber = exists $params{clobber} ? $params{clobber} : 1; + + map { $form->{$_} = $data->{$_} if $clobber || !exists $form->{$_} } keys %{ $data }; + + return $self; +} + +sub expire_session_keys { + my ($self) = @_; + + $self->{SESSION} ||= { }; + + my @now = gettimeofday(); + my $now = $now[0] * 1000000 + $now[1]; + + $self->delete_session_value(map { $_->[0] } + grep { $_->[1]->{expiration} && ($now > $_->[1]->{expiration}) } + map { [ $_, $self->_load_value($self->{SESSION}->{$_}) ] } + keys %{ $self->{SESSION} }); + + return $self; +} + +sub _has_expiration { + my ($value) = @_; + return (ref $value eq 'HASH') && exists($value->{expiration}) && $value->{data}; } sub set_cookie_environment_variable { @@ -1067,3 +1154,93 @@ sub load_rights_for_user { } 1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Auth - Authentication and session handling + +=head1 FUNCTIONS + +=over 4 + +=item C + +Store all key/value pairs in C<%values> in the session. All of these +values are copied back into C<$::form> in the next request +automatically. + +The values can be any Perl structure. They are stored as YAML dumps. + +=item C + +Retrieve a value from the session. Returns C if the value +doesn't exist. + +=item C + +Create a unique key in the session and store C<$value> +there. + +If C<$params{expiration}> is set then it is interpreted as a number of +seconds after which the value is removed from the session. It will +never expire if that parameter is falsish. + +If C<$params{auto_restore}> is trueish then the value will be copied +into C<$::form> upon the next request automatically. It defaults to +C and has therefore different behaviour than +L. + +Returns the key created in the session. + +=item C + +Removes all keys from the session that have an expiration time set and +whose expiration time is in the past. + +=item C + +Stores the session values in the database. This is the only function +that actually stores stuff in the database. Neither the various +setters nor the deleter access the database. + +=item + +Stores the content of C<$params{form}> (default: C<$::form>) in the +session using L. + +If C<$params{non_scalars}> is trueish then non-scalar values will be +stored as well. Default is to only store scalar values. + +The following keys will never be saved: C, C, +C, C, C. Additional keys not to save +can be given as an array ref in C<$params{skip_keys}>. + +Returns the unique key under which the form is stored. + +=item + +Restores the form from the session into C<$params{form}> (default: +C<$::form>). + +If C<$params{clobber}> is falsish then existing values with the same +key in C<$params{form}> will not be overwritten. C<$params{clobber}> +is on by default. + +Returns C<$self>. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index 880f6f471..6512f0312 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -233,7 +233,7 @@ sub handle_request { $::form = undef; $::myconfig = (); Form::disconnect_standard_dbh; - $::auth->save_session; + $::auth->expire_session_keys->save_session; $::auth->dbdisconnect; $::lxdebug->end_request; -- 2.20.1