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