Cindy Wang (CindyLinz)

NAME

Plack::Middleware::Session::SerializedCookie - Session middleware that saves session data in the customizable serialized cookie

SYNOPSIS

  # With serialize/deserialize subs

  enable "Session::SerializedCookie",
    serialize => sub {
        my $session = shift;
        ...
        return $serialized_session
    },
    deserialize => sub {
        my $serialized_session = shift;
        ...
    return $session };


  # With Serializer (object that
  #   implements 'serialize' and 'deserialize')

  enable "Session::SerializedCookie",
    serializer => Data::Serializer->new(...);


  # Mixed case

  my $serializer = Data::Serializer->new(...);
  enable "Session::SerializedCookie",
    serializer => $serializer,
    deserialize => sub {
        my $session = eval { $serializer->deserialize(@_) };
        $session = { ... (initial session) ... } if $@;
        return $session;
    };
  # The missing sub 'serialize' will fall back
  #   to use the serializer's one.


  # Additional exception handler

  enable "Session::SerializedCookie",
    serializer => Data::Serializer->new(...),
    serialize_exception => sub { my $error_msg = shift; ... },
    deserialize_exception => sub { my $error_msg = shift; ... };


  # In the app

  sub {
    my $env = shift;

    # Retrieve the session by $env->{'psgix.session'}
    # If the session is not presented, or something goes wrong when retrieving,
    # it'll be set to {}, an empty hash reference.
    my $session = $env->{'psgix.session'};
    ...

    $session->{blah} = 'blah blah';

    # At the end of the app, $env->{'psgix.session'} will be stored
    # to the cookie automatically.
    # To expire the session, undef the $env->{'psgix.session'} or
    # set $env->{'psgix.session.option'}{expire} = 1
  };


  # For full and more examples, take a look on eg/ directory.

DESCRIPTION

This middleware component works like Plack::Middleware::Session, that it provide a simple way to retrieve and store session data via $env->{'psgix.session'}. It store the session data in the cookie like what Plack::Middleware::Session::Cookie do, that doesn't need to store any data in the server side.

In addition, this module provide a convenient way to customize the way to serialize / deserialize the session data.

It is sometimes important to customize the serializer because of various application. Someone might need to store critical data in the session. Someone might need to store large data there. Some one might need just a simplest and fastest one, and don't care if the user can arbitrarily modify the session data.

CONFIGURATIONS

session_key

This is used as the cookie name

path, domain, secure

These are used as the cookie params. See Plack::Response for these options.

expires

This one is used as an advance time from the request time.

serialize

Set this attribute to a sub reference. It will be called when serializing. The only argument is the session data, $env->{'psgix.session'} in fact. And this sub should return the serialized one.

If this attribute is not presented. This module will try to use the serializer's member sub 'serialize'.

deserialize

Set this attribute to a sub reference. It is the inverse of serialize. It will get the serialized session as the only argument, and should return the session data.

Like 'serialize', if this attribute is missed, the module will try to use serializer's one.

serializer

Set this attribute to an object. When 'serialize' or 'deserialize' is missed, the module will use this object's.

serialize_exception, deserialize_exception

If there is anything wrong when serializing or deserializing, the coresponding sub will be called with the error message ($@) as the only argument.

Note that exception is expensive. You should avoid exception when possible, if the efficiency is important at your application.

CONSIDERATION

When customizing your own serializing method, there are some issues that you might need to consider.

serializer

This is the primary part of serialization, to transform a bunch of data into a string, and to transform a string back to the original data.

There are several well-known serialization method, such as Data::Dumper, JSON, YAML, PHP::Serialization, Data::DumpXML, etc. Each of them has different benefits and different limits. You should read their documents for more information.

My favorite one is JSON. It will try to use JSON::XS when availible. This one is both efficient and simple. Though you can only store opaque data structure with array reference, hash reference, string, and number data types. You can't store other types such as code reference, blessed object, tied data, nor references that refer to the same variable or cyclic references (JSON will extract them independently and completely).

base64

It's not allowed to use all the octet codes as the cookie value. It's a safer way to encode your serialized string into base64 form. You may take a look on MIME::Base64.

Note, you should use this as the final filter, or it will be useless.

encryption

Sometimes, you may want to store critical data in the session, that you don't want the user to know what you have store there. You may consider to encrypt the session. My favorite one is AES (Crypt::Rijndael).

Besides, to encrypt session can avoid the user to change the session. If you just want to prevent the user to change the session, but don't care if the user could read its content, it's not neccessary to encrypt it. You can use signature instead. See the section "signature".

compression

The browser will not allow to store very large cookie data. You may need to compress it. Though, to think of storing smaller data in session might be a much better approach.

You may use Compress::Zlib to achieve this.

additional data

Besides to filter the whole session, you may want to just put additional data, that could help you to do some verification.

You can store the additional data by concating them with the serialized string (if they are string form already),

  $serialized_session = join ',', $serialized_session, $addition1, $addition2

or more generally injecting into the session data structure before serialization.

  $session = [$session, $addition1, $addition2]
signature

Use a one-way hash function to generate the signature from the serialized session string and a secret string. The users cannot generate the signatures by themselves without knowing about the secret string. So they can't generate arbitrary session data with correct signatures.

There are many one-way hash functions availible, such as SHA1, SHA2, MD5, MD6, etc.

It's no need to use signature, if you've encrypted the session.

timestamp

With timestamp, you can expire old session strictly. That is, even the browser never expires the cookie, you can still expire it by rejecting old timestamp.

ip address

This is a more aggresive way to prevent the unwelcome bad guy from stealing the session.

Use this feature cautiously. It will block users who change their ip address rapidly. On the other hand, it's useless if the bad guy is using the same ip address as the user, 'cause they are at the same intranet, or the bad guy is the spyware on the same computer.

AUTHOR

Cindy Wang (CindyLinz)

SEE ALSO

Plack::Middleware::Session Plack::Middleware::Session::Cookie