Skip to content

Commit

Permalink
sessioning docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdonc committed Oct 29, 2010
1 parent 9682095 commit 04ebd57
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 14 deletions.
1 change: 1 addition & 0 deletions docs/api.rst
Expand Up @@ -25,6 +25,7 @@ documentation is organized alphabetically by module name.
api/router
api/scripting
api/security
api/session
api/settings
api/testing
api/threadlocal
Expand Down
4 changes: 4 additions & 0 deletions docs/api/interfaces.rst
Expand Up @@ -25,3 +25,7 @@ Other Interfaces

.. autointerface:: IRoutePregenerator

.. autointerface:: ISession

.. autointerface:: ISessionFactory

8 changes: 8 additions & 0 deletions docs/api/request.rst
Expand Up @@ -85,3 +85,11 @@
of ``request.exception`` will be ``None`` within response and
finished callbacks.

.. attribute:: session

If a :term:`session factory` has been configured, this attribute
will represent the current user's :term:`session` object. If a
session factory *has not* been configured, requesting the
``request.session`` attribute will cause a
:class:`pyramid.exceptions.ConfigurationError` to be raised.

9 changes: 9 additions & 0 deletions docs/api/session.rst
@@ -0,0 +1,9 @@
.. _session_module:

:mod:`pyramid.session`
---------------------------

.. automodule:: pyramid.session

.. autofunction:: InsecureCookieSessionFactoryConfig

11 changes: 11 additions & 0 deletions docs/glossary.rst
Expand Up @@ -803,3 +803,14 @@ Glossary
``route_url``. See
:class:`repoze.bfg.interfaces.IRoutePregenerator` for more
information.

session
A namespace that is valid for some period of continual activity
that can be used to represent a user's interaction with a web
application.

session factory
A callable, which, when called with a single argument named
``request`` (a :term:`request` object), returns a
:term:`session` object.

1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -40,6 +40,7 @@ Narrative documentation in chapter form explaining how to use
narr/views
narr/static
narr/webob
narr/sessions
narr/templates
narr/models
narr/security
Expand Down
2 changes: 1 addition & 1 deletion docs/narr/security.rst
Expand Up @@ -241,7 +241,7 @@ application:

When a default permission is registered:

- if a view configuration names an explicit ``permission`, the default
- if a view configuration names an explicit ``permission``, the default
permission is ignored for that view registration, and the
view-configuration-named permission is used.

Expand Down
152 changes: 152 additions & 0 deletions docs/narr/sessions.rst
@@ -0,0 +1,152 @@
.. index::
single: session

.. _sessions_chapter:

Session Objects
===============

A :term:`session` is a namespace which is valid for some period of
continual activity that can be used to represent a user's interaction
with a web application.

Using The Default Session Factory
---------------------------------

In order to use sessions, you must set up a :term:`session factory`
during your :mod:`pyramid` configuration.

A very basic, insecure sample session factory implementation is
provided in the :mod:`pyramid` core. It uses a cookie to store
session information. This implementation has the following
limitation:

- The session information in the cookies used by this implementation
is *not* encrypted, so it can be viewed by anyone with access to the
cookie storage of the user's browser or anyone with access to the
network along which the cookie travels.

- The maximum number of bytes that are storable in a serialized
representation of the session is fewer than 4000. Only very small
data sets can be kept in this

It is, however, digitally signed, and thus its data cannot easily be
tampered with.

You can configure this session factory in your :mod:`pyramid`
application by using the ``session_factory`` argument to the
:class:`pyramid.configuration.Configurator` class:

.. code-block:: python
:linenos:
from pyramid.session import InsecureCookieSessionFactoryConfig
my_session_factory = InsecureCookieSessionFactoryConfig('itsaseekreet')
from pyramid.configuration import Configurator
config = Configurator(session_factory = my_session_factory)
.. warning::

Note the very long, very explicit name for
``InsecureCookieSessionFactoryConfig``. It's trying to tell you
that this implementation is, by default, *insecure*. You should
not use it when you keep sensitive information in the session
object, as the information can be easily read by both users of your
application and third parties who have access to your users'
network traffic. Use a different session factory implementation
(preferably one which keeps session data on the server) for
anything but the most basic of applications where "session security
doesn't matter".

Using a Session Object
----------------------

Once a session factory has been configured for your application, you
can access session objects provided by the session factory by asking
for the ``session`` attribute of any :term:`request` object. For
example:

.. code-block:: python
:linenos:
from webob import Response
def myview(request):
session = request.session
if 'abc' in session:
session['fred'] = 'yes'
session['abc'] = '123'
if 'fred' in session:
return Response('Fred was in the session')
else:
return Response('Fred was not in the session')
You can use a session much like a Python dictionary. It supports all
methods of a Python dictionary, and it has three extra attributes, and
two extra methods.

Extra attributes:

``modified``
An integer timestamp indicating the last time the session was modified.

``created``
An integer timestamp indicating the time that this session was created.

``new``
A boolean. If ``new`` is True, this session is new. Otherwise, it has
been constituted from data that was already serialized.

Extra methods:

``changed()``
Call this when you mutate a mutable value in the session namespace.

``invalidate()``
Call this when you want to invalidate the session (dump all data,
and -- perhaps -- set a clearing cookie).

The formal definition of the methods and attributes supported by the
session object are in the :class:`pyramid.interfaces.ISession`
documentation.

Some gotchas:

- Keys and values of session data must be *pickleable*. This means,
typically, that they must be instances of basic types of objects,
such as strings, lists, dictionaries, tuples, integers, etc. If you
place an object in a session data key or value that is not
pickleable, an error will be raised when the session is serialized.

- If you place a mutable value (for example, a list or a dictionary)
in a session object, and you subsequently mutate that value, you
must call the ``changed()`` method of the session object. This is
because, although the session object can detect when you call its
data-modifying methods such as ``__setitem__``, ``pop`` and other
(and thus the session knows it needs to reserialize the session
data), when you change a mutable object stored in the session
itself, the session has no way to know that you changed that value.
When in doubt, call ``changed()`` after you've changed sessioning
data.

Using Alternate Session Factories
---------------------------------

At the time of this writing, alternate session factories don't yet
exist. It is our intent that we will soon provide at least one other
session factory which will be easily installable: one that uses the
`Beaker <http://beaker.groovie.org/>`_ library as a backend.

Creating Your Own Session Factory
---------------------------------

If none of the default or otherwise available sessioning
implementations for :mod:`pyramid` suit you, you may create your own
session object by implementing a :term:`session factory`. Your
session factory should return a :term:`session`. The interfaces for
both types are available in
:class:`pyramid.interfaces.ISessionFactory` and
:class:`pyramid.interfaces.ISession`. You might use the cookie
implementation in the :mod:`pyramid.session` module as inspiration.

12 changes: 6 additions & 6 deletions docs/narr/webob.rst
Expand Up @@ -109,12 +109,12 @@ instance, ``req.if_modified_since`` returns a `datetime
Special Attributes Added to the Request by :mod:`pyramid`
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In addition to the standard :term:`WebOb` attributes,
:mod:`pyramid` adds special attributes to every request:
``context``, ``registry``, ``root``, ``subpath``, ``traversed``,
``view_name``, ``virtual_root`` , and ``virtual_root_path``. These
attributes are documented further within the
:class:`pyramid.request.Request` API documentation.
In addition to the standard :term:`WebOb` attributes, :mod:`pyramid`
adds special attributes to every request: ``context``, ``registry``,
``root``, ``subpath``, ``traversed``, ``view_name``, ``virtual_root``
, ``virtual_root_path``, and ``session``. These attributes are
documented further within the :class:`pyramid.request.Request` API
documentation.

.. index::
single: request URLs
Expand Down
12 changes: 6 additions & 6 deletions pyramid/interfaces.py
Expand Up @@ -424,7 +424,7 @@ def changed():
def __getitem__(key):
"""Get a value for a key
A KeyError is raised if there is no value for the key.
A ``KeyError`` is raised if there is no value for the key.
"""

def get(key, default=None):
Expand All @@ -436,7 +436,7 @@ def get(key, default=None):
def __delitem__(key):
"""Delete a value from the mapping using the key.
A KeyError is raised if there is no value for the key.
A ``KeyError`` is raised if there is no value for the key.
"""

def __setitem__(key, value):
Expand Down Expand Up @@ -470,17 +470,17 @@ def update(d):
" Update D from E: for k in E.keys(): D[k] = E[k]"

def setdefault(key, default=None):
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
" D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D "

def pop(k, *args):
"""remove specified key and return the corresponding value
*args may contain a single default value, or may not be supplied.
``*args`` may contain a single default value, or may not be supplied.
If key is not found, default is returned if given, otherwise
KeyError is raised"""
``KeyError`` is raised"""

def popitem():
"""remove and return some (key, value) pair as a
2-tuple; but raise KeyError if mapping is empty"""
2-tuple; but raise ``KeyError`` if mapping is empty"""

def __len__():
"""Return the number of items in the session.
Expand Down
2 changes: 1 addition & 1 deletion pyramid/request.py
Expand Up @@ -151,7 +151,7 @@ def session(self):
if factory is None:
raise ConfigurationError(
'No session factory registered '
'(use ``config.add_session_factory``)')
'(see the Session Objects chapter of the documentation)')
return factory(self)

# override default WebOb "environ['adhoc_attr']" mutation behavior
Expand Down
46 changes: 46 additions & 0 deletions pyramid/session.py
Expand Up @@ -49,6 +49,52 @@ def InsecureCookieSessionFactoryConfig(
cookie_httponly=False,
cookie_on_exception=False,
):
"""
Configure a :term:`session factory` which will provide insecure
(but signed) cookie-based sessions. The return value of this
function is a :term:`session factory`, which may be provided as
the ``session_factory`` argument of a
:class:`pyramid.configuration.Configurator` constructor, or used
as the ``session_factory`` argument of the
:meth:`pyramid.configuration.Configurator.set_session_factory`
method.
The session factory returned by this function will create sessions
which are limited to storing fewer than 4000 bytes of data (as the
payload must fit into a single cookie).
Parameters:
``secret``
A string which is used to sign the cookie.
``timeout``
A number of seconds of inactivity before a session times out.
``cookie_name``
The name of the cookie used for sessioning. Default: ``session``.
``cookie_max_age``
The maximum age of the cookie used for sessioning (in seconds).
Default: ``None`` (browser scope).
``cookie_path``
The path used for the session cookie. Default: ``/``.
``cookie_domain``
The domain used for the session cookie. Default: ``None`` (no domain).
``cookie_secure``
The 'secure' flag of the session cookie. Default: ``False``.
``cookie_httponly``
The 'httpOnly' flag of the session cookie. Default: ``False``.
``cookie_on_exception``
If ``True``, set a session cookie even if an exception occurs
while rendering a view. Default: ``False``.
"""

class InsecureCookieSessionFactory(dict):
""" Dictionary-like session object """
Expand Down

0 comments on commit 04ebd57

Please sign in to comment.