3 package Catalyst::Plugin::Session;
4 use base qw/Class::Accessor::Fast/;
10 use Catalyst::Exception ();
16 __PACKAGE__->mk_accessors(qw/sessionid session_delete_reason/);
24 $c->check_session_plugin_requirements;
30 sub check_session_plugin_requirements {
33 unless ( $c->isa("Catalyst::Plugin::Session::State")
34 && $c->isa("Catalyst::Plugin::Session::Store") )
37 ( "The Session plugin requires both Session::State "
38 . "and Session::Store plugins to be used as well." );
41 Catalyst::Exception->throw($err);
48 my $cfg = ( $c->config->{session} ||= {} );
56 $c->NEXT::setup_session();
62 if ( $c->{session} ) {
64 # all sessions are extended at the end of the request
66 @{ $c->{session} }{qw/__updated __expires/} =
67 ( $now, $c->config->{session}{expires} + $now );
68 $c->store_session_data( $c->sessionid, $c->{session} );
71 $c->NEXT::finalize(@_);
77 my $ret = $c->NEXT::prepare_action;
79 my $sid = $c->sessionid || return;
81 $c->log->debug(qq/Found session "$sid"/) if $c->debug;
83 my $s = $c->{session} ||= $c->get_session_data($sid);
84 if ( !$s or $s->{__expires} < time ) {
87 $c->log->debug("Deleting session $sid (expired)") if $c->debug;
88 $c->delete_session("session expired");
92 if ( $c->config->{session}{verify_address}
93 && $c->{session}{__address}
94 && $c->{session}{__address} ne $c->request->address )
97 "Deleting session $sid due to address mismatch ("
98 . $c->{session}{__address} . " != "
99 . $c->request->address . ")",
101 $c->delete_session("address mismatch");
107 my ( $c, $msg ) = @_;
109 # delete the session data
110 my $sid = $c->sessionid;
111 $c->delete_session_data($sid);
113 # reset the values in the context object
114 $c->{session} = undef;
115 $c->sessionid(undef);
116 $c->session_delete_reason($msg);
122 return $c->{session} if $c->{session};
124 my $sid = $c->generate_session_id;
127 $c->log->debug(qq/Created session "$sid"/) if $c->debug;
129 return $c->initialize_session_data;
132 sub initialize_session_data {
137 return $c->{session} = {
140 __expires => $now + $c->config->{session}{expires},
143 $c->config->{session}{verify_address}
144 ? ( __address => $c->request->address )
150 # refactor into Catalyst::Plugin::Session::ID::Weak ?
152 sub generate_session_id {
155 my $digest = $c->_find_digest();
156 $digest->add( $c->session_hash_seed() );
157 return $digest->hexdigest;
162 sub session_hash_seed {
165 return join( "", ++$counter, time, rand, $$, {}, overload::StrVal($c), );
170 sub _find_digest () {
172 $usable = List::Util::first(
174 eval { Digest->new($_) };
176 qw/SHA-1 MD5 SHA-256/
178 or Catalyst::Exception->throw(
179 "Could not find a suitable Digest module. Please install "
180 . "Digest::SHA1, Digest::SHA, or Digest::MD5" );
183 return Digest->new($usable);
194 Catalyst::Plugin::Session - Generic Session plugin - ties together server side
195 storage and client side tickets required to maintain session data.
199 use Catalyst qw/Session Session::Store::FastMmap Session::State::Cookie/;
203 The Session plugin is the base of two related parts of functionality required
204 for session management in web applications.
206 The first part, the State, is getting the browser to repeat back a session key,
207 so that the web application can identify the client and logically string
208 several requests together into a session.
210 The second part, the Store, deals with the actual storage of information about
211 the client. This data is stored so that the it may be revived for every request
212 made by the same client.
214 This plugin links the two pieces together.
222 An accessor for the session ID value.
226 Returns a hash reference that might contain unserialized values from previous
227 requests in the same session, and whose modified value will be saved for future
230 This method will automatically create a new session and session ID if none
233 =item session_delete_reason
235 This accessor contains a string with the reason a session was deleted. Possible
252 This method is extended to also make calls to
253 C<check_session_plugin_requirements> and C<setup_session>.
255 =item check_session_plugin_requirements
257 This method ensures that a State and a Store plugin are also in use by the
262 This method populates C<< $c->config->{session} >> with the default values
263 listed in L</CONFIGURATION>.
267 This methoid is extended, and will restore session data and check it for
268 validity if a session id is defined. It assumes that the State plugin will
269 populate the C<sessionid> key beforehand.
273 This method is extended and will extend the expiry time, as well as persist the
274 session data if a session exists.
276 =item delete_session REASON
278 This method is used to invalidate a session. It takes an optional parameter
279 which will be saved in C<session_delete_reason> if provided.
281 =item initialize_session_data
283 This method will initialize the internal structure of the session, and is
284 called by the C<session> method if appropriate.
290 $c->config->{session} = {
294 All configuation parameters are provided in a hash reference under the
295 C<session> key in the configuration hash.
301 The time-to-live of each session, expressed in seconds. Defaults to 7200 (two
306 When false, C<< $c->request->address >> will be checked at prepare time. If it
307 is not the same as the address that initiated the session, the session is
314 The hash reference returned by C<< $c->session >> contains several keys which
315 are automatically set:
321 A timestamp whose value is the last second when the session is still valid. If
322 a session is restored, and __expires is less than the current time, the session
327 The last time a session was saved. This is the value of
328 C<< $c->{session}{__expires} - $c->config->{session}{expires} >>.
332 The time when the session was first created.
336 The value of C<< $c->request->address >> at the time the session was created.
337 This value is only populated of C<verify_address> is true in the configuration.