Catalyst::Plugin::Session::Tutorial man page on Fedora

Man page or keyword search:  
man Server   31170 pages
apropos Keyword Search (all sections)
Output format
Fedora logo
[printable version]

Catalyst::Plugin::SessUser:Contributed PCatalyst::Plugin::Session::Tutorial(3)

NAME
       Catalyst::Plugin::Session::Tutorial - Understanding and using sessions.

ASSUMPTIONS
       This tutorial assumes that you are familiar with web applications in
       general and Catalyst specifically (up to models and configuration), and
       that you know what HTTP is.

WHAT ARE SESSIONS
       When users use a site, especially one that knows who they are (sites
       you log in to, sites which let you keep a shopping cart, etc.), the
       server preparing the content has to know that request X comes from
       client A while request Y comes from client B, so that each user gets
       the content meant for them.

       The problem is that HTTP is a stateless protocol. This means that every
       request is distinct, and even if it comes from the same client, it's
       difficult to know that.

       The way sessions are maintained between distinct requests is that the
       client says, for every request, "I'm client A" or "I'm client B".

       This piece of data that tells the server "I'm X" is called the session
       ID, and the threading of several requests together is called a session.

HOW SESSIONS WORK
   Cookies
       HTTP has a feature that lets this become easier, called cookies. A
       cookie is something the server asks the client to save somewhere, and
       resend every time a request is made.

       The way they work is that the server sends the "Set-Cookie" header,
       with a cookie name, a value, and some metadata (like when it expires,
       what paths it applies to, etc.). The client saves this.

       Then, on every subsequent request the client will send a "Cookie"
       header, with the cookie name and value.

   Cookie Alternatives
       Another way is to make sure that the session ID is repeated is to
       include it in every URI.

       This can be as either a part of the path, or as a query parameter.

       This technique has several issues which are discussed in "CAVEATS" in
       Catalyst::Plugin::Session::State::URI.

   Server-Side Behavior
       When the server receives the session ID it can then look this key up in
       a database of some sort. For example the database can contain a
       shopping cart's contents, user preferences, etc.

USING SESSIONS
       In Catalyst, the Catalyst::Plugin::Session plugin provides an API for
       convenient handling of session data. This API is based on the older,
       less flexible and less reliable Catalyst::Plugin::Session::FastMmap.

       The plugin is modular, and requires backend plugins to be used.

   State Plugins
       State plugins handle session ID persistence. For example
       Catalyst::Plugin::Session::State::Cookie creates a cookie with the
       session ID in it.

       These plugins will automatically set "$c->sessionid" at the beginning
       of the request, and automatically cause "$c->sessionid" to be saved by
       the client at the end of the request.

   Store Plugins
       The backend into which session data is stored is provided by these
       plugins. For example, Catalyst::Plugin::Session::Store::DBI uses a
       database table to store session data, while
       Catalyst::Plugin::Session::Store::FastMmap uses Cache::FastMmap.

   Configuration
       First you need to load the appropriate plugins into your Catalyst
       application:

	   package MyApp;

	   use Catalyst qw/
	       Session
	       Session::State::Cookie
	       Session::Store::File
	   /;

       This loads the session API, as well as the required backends of your
       choice.

       After the plugins are loaded they need to be configured. This is done
       according to "Configure_your_application" in
       Catalyst::Manual::Cookbook.

       Each backend plugin requires its own configuration options (with most
       plugins providing sensible defaults). The session API itself also has
       configurable options listed in "CONFIGURATION" in
       Catalyst::Plugin::Session.

       For the plugins above we don't need any configuration at all - they
       should work out of the box, but suppose we did want to change some
       things around, it'll look like this:

	   MyApp->config( 'Plugin::Session' => {
	       cookie_name => "my_fabulous_cookie",
	       storage	   => "/path/to/store_data_file",
	   });

   Usage
       Now, let's say we have an online shop, and the user is adding an item
       to the shopping cart.

       Typically the item the user was viewing would have a form or link that
       adds the item to the cart.

       Suppose this link goes to "/cart/add/foo_baz/2", meaning that we want
       two units of the item "foo_baz" to be added to the cart.

       Our "add" action should look something like this:

	   package MyApp::Controller::Cart;

	   sub add : Local {
	       my ( $self, $c, $item_id, $quantity ) = @_;
	       $quantity ||= 1;

	       if ( $c->model("Items")->item_exists($item_id) ) {
		   $c->session->{cart}{$item_id} += $quantity;
	       } else {
		   die "No such item";
	       }
	   }

       The way this works is that "$c->session" always returns a hash
       reference to some data which is stored by the storage backend plugin.
       The hash reference returned always contains the same items that were in
       there at the end of the last request.

       All the mishmash described above is done automatically. First, the
       method looks to see if a session ID is set. This session ID will be set
       by the State plugin if appropriate, at the start of the request (e.g.
       by looking at the cookies sent by the client).

       If a session ID is set, the store will be asked to retrieve the session
       data for that specific session ID, and this is returned from
       "$c->session". This retrieval is cached, and will only happen once per
       request, if at all.

       If a session ID is not set, a new one is generated, a new anonymous
       hash is created and saved in the store with the session ID as the key,
       and the reference to the hash is returned.

       The action above takes this hash reference, and updates a nested hash
       within it, that counts quantity of each item as stored in the cart.

       Any cart-listing code can then look into the session data and use it to
       display the correct items, which will, of course, be remembered across
       requests.

       Here is an action some Template Toolkit example code that could be used
       to generate a cart listing:

	   sub list_cart : Local {
	       my ( $self, $c ) = @_;

	       # get the cart data, that maps from item_id to quantity
	       my $cart = $c->session->{cart} || {};

	       # this is our abstract model in which items are stored
	       my $storage = $c->model("Items");

	       # map from item_id to item (an object or hash reference)
	       my %items = map { $_ => $storage->get_item($_) } keys %$cart;

	       # put the relevant info on the stash
	       $c->stash->{cart}{items} = \%items;
	       $c->stash->{cart}{quantity} = $cart;
	   }

       And [a part of] the template it forwards to:

	   <table>

	       <thead>
		   <tr>
		       <th>Item</th>
		       <th>Quantity</th>
		       <th>Price</th>
		       <th>remove</th>
		   </tr>
	       </thead>

	       <tbody>
	       [%# the table body lists all the items in the cart %]
	       [% FOREACH item_id = cart.items.keys %]

		   [%# each item has its own row in the table %]

		   [% item = cart.items.$item_id %]
		   [% quantity = cart.quantity.$item_id %]

		   <tr>
		       <td>
			   [%# item.name is an attribute in the item
			     # object, as loaded from the store %]
			   [% item.name %]
		       </td>

		       <td>
			   [%# supposedly this is part of a form where you
			     # can update the quantity %]
			   <input type="text" name="[% item_id %]_quantity"
			       value="[% quantity %]" />
		       </td>

		       <td> $ [% item.price * quantity %] </td>

		       <td>
			   <a href="[% c.uri_for('/cart/remove') %]/[% item_id %]">
			       <img src="/static/trash_can.png" />
			   </a>
		       </td>
	       [% END %]
	       <tbody>

	       <tfoot>
		   <tr>
		       <td colspan="2"> Total: </td>
		       <td>
			   [%# calculate sum in this cell - too
			     # much headache for a tutorial ;-) %]
		       </td>
		       <td>
			   <a href="[% c.uri_for('/cart/empty') %]">Empty cart</a>
		       </td>
		   </tr>
	       </tfoot>

	   </table>

       As you can see the way that items are added into "$c->session->{cart}"
       is pretty simple. Since "$c->session" is restored as necessary, and
       contains data from previous requests by the same client, the cart can
       be updated as the user navigates the site pretty transparently.

SECURITY ISSUES
       These issues all relate to how session data is managed, as described
       above.  These are not issues you should be concerned about in your
       application code, but are here for their educational value.

   (Not) Trusting the Client
       In order to avoid the overhead of server-side data storage, the session
       data can be included in the cookie itself.

       There are two problems with this:

       1.  The user can change the data.

       2.  Cookies have a 4 kilobyte size limit.

	   The size limit is of no concern in this section, but data changing
	   is. In the database scheme the data can be trusted, since the user
	   can neither read nor write it. However, if the data is delegated to
	   the user, then special measures have to be added for ensuring data
	   integrity, and perhaps secrecy too.

	   This can be implemented by encrypting and signing the cookie data,
	   but this is a big headache.

   Session Hijacking
       What happens when client B says "I'm client A"?	Well, basically, the
       server buys it. There's no real way around it.

       The solution is to make "I'm client A" a difficult thing to say. This
       is why session IDs are randomized. If they are properly randomized,
       session IDs are so hard to guess that they must be stolen instead.

       This is called session hijacking. There are several ways one might
       hijack another user's session.

       Cross Site Scripting

       One is by using cross site scripting attacks to steal the cookie data.
       In community sites, where users can cause the server to display
       arbitrary HTML, they can use this to put JavaScript code on the server.

       If the server does not enforce a strict subset of tags that may be
       used, the malicious user could use this code to steal the cookies
       (there is a JavaScript API that lets cookies be accessed, but this code
       has to be run on the same website that the cookie came from).

       Social Engineering

       By tricking a user into revealing a URI with session data embedded in
       it (when cookies are not used), the session ID can also be stolen.

       Also, a naive user could be tricked into showing the cookie data from
       the browser to a malicious user.

AUTHOR
       Yuval Kogman <nothingmuch@woobling.org>

perl v5.14.1			  2010-0Catalyst::Plugin::Session::Tutorial(3)
[top]

List of man pages available for Fedora

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net