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