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