Some cleanup of the code.
[catagits/Web-Session.git] / lib / Plack / Middleware / Session / Cookie.pm
CommitLineData
d326e755 1package Plack::Middleware::Session::Cookie;
2use strict;
3use parent qw(Plack::Middleware::Session);
4
5use Plack::Util::Accessor qw(secret session_key domain expires path secure);
6
7use Digest::HMAC_SHA1;
8use MIME::Base64 ();
9use Storable ();
10use Time::HiRes;
11use Plack::Util;
12
13use Plack::Session::State::Cookie;
14
15sub prepare_app {
16 my $self = shift;
17
4ff41723 18 Plack::Util::load_class($self->session_class) if $self->session_class;
d326e755 19 $self->session_key("plack_session") unless $self->session_key;
20
21 my $state_cookie = Plack::Session::State::Cookie->new;
22 for my $attr (qw(session_key path domain expires secure)) {
23 $state_cookie->$attr($self->$attr);
24 }
25
26 my $state = Plack::Util::inline_object
27 generate => sub { $self->_serialize({}) },
28 extract => sub {
29 my $cookie = $state_cookie->get_session_id(@_) or return;
30
31 my($time, $b64, $sig) = split /:/, $cookie, 3;
32 $self->sig($b64) eq $sig or return;
33
34 return $cookie;
35 },
36 expire_session_id => sub { $state_cookie->expire_session_id(@_) },
4ff41723 37 finalize => sub { $state_cookie->finalize(@_) };
d326e755 38
39 my $store = Plack::Util::inline_object
40 fetch => sub {
41 my $id = shift;
42 my($time, $b64, $sig) = split /:/, $id, 3;
43 Storable::thaw(MIME::Base64::decode($b64));
44 },
45 store => sub { },
46 cleanup => sub { };
47
48 $self->state($state);
49 $self->store($store);
50}
51
4ff41723 52sub finalize {
98b27b31 53 my($self, $session, $options, $response) = @_;
4ff41723 54
98b27b31 55 if ($options->{expire}) {
56 $self->state->expire_session_id($options->{id}, $response);
4ff41723 57 } else {
98b27b31 58 my $cookie = $self->_serialize($session);
59 $self->state->finalize($cookie, $response, $options);
4ff41723 60 }
61}
62
d326e755 63sub _serialize {
64 my($self, $session) = @_;
65
66 my $now = Time::HiRes::gettimeofday;
67 my $b64 = MIME::Base64::encode( Storable::freeze($session), '' );
68 join ":", $now, $b64, $self->sig($b64);
69}
70
71sub sig {
72 my($self, $b64) = @_;
73 return '.' unless $self->secret;
74 Digest::HMAC_SHA1::hmac_sha1_hex($b64, $self->secret);
75}
76
771;
78
79__END__
80
81=head1 NAME
82
83Plack::Middleware::Session::Cookie - Session middleware that saves session data in the cookie
84
85=head1 SYNOPSIS
86
87 enable "Session::Cookie";
88
89=head1 DESCRIPTION
90
91This middleware component allows you to use the cookie as a sole
92cookie state and store, without any server side storage to do the
93session management. This middleware utilizes its own state and store
94automatically for you, so you can't override the objects.
95
96=head1 CONFIGURATIONS
97
98This middleware is a subclass of L<Plack::Middleware::Session> and
99accepts most configuration of the parent class. In addition, following
100options are accepted.
101
102=over 4
103
104=item secret
105
106Server side secret to sign the session data using HMAC SHA1. Defaults
107to nothing (i.e. do not sign) but B<strongly recommended> to set your
108own secret string.
109
110=item session_key, domain, expires, path, secure
111
112Accessors for the cookie attribuets. See
113L<Plack::Session::State::Cookie> for these options.
114
115=back
116
117=head1 AUTHOR
118
119Tatsuhiko Miyagawa
120
121=head1 SEE ALSO
122
123Rack::Session::Cookie L<Dancer::Session::Cookie>
124
125=cut
126