summaryrefslogtreecommitdiff
path: root/docs/narr/sessions.rst
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-01-08 00:17:29 -0500
committerChris McDonough <chrism@plope.com>2011-01-08 00:17:29 -0500
commit134c5cb12490ff357e5ee0917c42a87140249a04 (patch)
treeb606219aeb0ae605e3768852827269bf81bda51e /docs/narr/sessions.rst
parent14f863d9b5c323303155c79901f22c5d0e1dbe69 (diff)
parentf7f0dd818138f3a4284fe1614a66dc121c9da86c (diff)
downloadpyramid-134c5cb12490ff357e5ee0917c42a87140249a04.tar.gz
pyramid-134c5cb12490ff357e5ee0917c42a87140249a04.tar.bz2
pyramid-134c5cb12490ff357e5ee0917c42a87140249a04.zip
Merge branch 'caseman-master'
Diffstat (limited to 'docs/narr/sessions.rst')
-rw-r--r--docs/narr/sessions.rst186
1 files changed, 182 insertions, 4 deletions
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index de9add3b7..842b838cd 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -3,13 +3,18 @@
.. _sessions_chapter:
-Session Objects
-===============
+Sessions
+========
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.
+This chapter describes how to configure sessions, what session
+implementations :app:`Pyramid` provides out of the box, how to store and
+retrieve data from sessions, and two session-specific features: flash
+messages, and cross-site request forgery attack prevention.
+
.. _using_the_default_session_factory:
Using The Default Session Factory
@@ -32,7 +37,7 @@ limitation:
representation of the session is fewer than 4000. This is
suitable only for very small data sets.
-It is, however, digitally signed, and thus its data cannot easily be
+It is digitally signed, however, and thus its data cannot easily be
tampered with.
You can configure this session factory in your :app:`Pyramid`
@@ -113,7 +118,7 @@ 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,
+ typically, that they are 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.
@@ -162,3 +167,176 @@ both types are available in
:class:`pyramid.interfaces.ISession`. You might use the cookie
implementation in the :mod:`pyramid.session` module as inspiration.
+.. index::
+ single: flash messages
+
+Flash Messages
+--------------
+
+"Flash messages" are simply a queue of message strings stored in the
+:term:`session`. To use flash messaging, you must enable a :term:`session
+factory` as described in :ref:`using_the_default_session_factory` or
+:ref:`using_alternate_session_factories`.
+
+Flash messaging has two main uses: to display a status message only once to
+the user after performing an internal redirect, and to allow generic code to
+log messages for single-time display without having direct access to an HTML
+template. The user interface consists of a number of methods of the
+:term:`session` object.
+
+Using the ``session.flash`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To add a message to a flash message queue, use a session object's ``flash()``
+method:
+
+.. code-block:: python
+
+ request.session.flash('mymessage')
+
+The ``flash()`` method appends a message to a flash queue, creating the queue
+if necessary.
+
+``flash()`` accepts three arguments:
+
+.. method:: flash(message, queue='', allow_duplicate=True)
+
+The ``message`` argument is required. It represents a message you wish to
+later display to a user. It is usually a string but the ``message`` you
+provide is not modified in any way.
+
+The ``queue`` argument allows you to choose a queue to which to append
+the message you provide. This can be used to push different kinds of
+messages into flash storage for later display in different places on a
+page. You can pass any name for your queue, but it must be a string.
+Each queue is independent, and can be popped by ``pop_flash()`` or
+examined via ``peek_flash()`` separately. ``queue`` defaults to the
+empty string. The empty string represents the default flash message
+queue.
+
+.. code-block:: python
+
+ request.session.flash(msg, 'myappsqueue')
+
+The ``allow_duplicate`` argument defaults to ``True``. If this is
+``False``, and you attempt to add a message value which is already
+present in the queue, it will not be added.
+
+Using the ``session.pop_flash`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once one or more messages have been added to a flash queue by the
+``session.flash()`` API, the ``session.pop_flash()`` API can be used to
+pop an entire queue and return it for use.
+
+To pop a particular queue of messages from the flash object, use the session
+object's ``pop_flash()`` method. This returns a list of the messages
+that were added to the flash queue, and empties the queue.
+
+.. method:: pop_flash(queue='')
+
+.. code-block:: python
+ :linenos:
+
+ >>> request.session.flash('info message')
+ >>> request.session.pop_flash()
+ ['info message']
+
+Calling ``session.pop_flash()`` again like above without a corresponding call
+to ``session.flash()`` will return an empty list, because the queue has already
+been popped.
+
+.. code-block:: python
+ :linenos:
+
+ >>> request.session.flash('info message')
+ >>> request.session.pop_flash()
+ ['info message']
+ >>> request.session.pop_flash()
+ []
+
+Using the ``session.peek_flash`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once one or more messages has been added to a flash queue by the
+``session.flash()`` API, the ``session.peek_flash()`` API can be used to
+"peek" at that queue. Unlike ``session.pop_flash()``, the queue is not
+popped from flash storage.
+
+.. method:: peek_flash(queue='')
+
+.. code-block:: python
+ :linenos:
+
+ >>> request.session.flash('info message')
+ >>> request.session.peek_flash()
+ ['info message']
+ >>> request.session.peek_flash()
+ ['info message']
+ >>> request.session.pop_flash()
+ ['info message']
+ >>> request.session.peek_flash()
+ []
+
+.. index::
+ single: preventing cross-site request forgery attacks
+ single: cross-site request forgery attacks, prevention
+
+Preventing Cross-Site Request Forgery Attacks
+---------------------------------------------
+
+`Cross-site request forgery
+<http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a
+phenomenon whereby a user with an identity on your website might click on a
+URL or button on another website which unwittingly redirects the user to your
+application to perform some command that requires elevated privileges.
+
+You can avoid most of these attacks by making sure that the correct *CSRF
+token* has been set in an :app:`Pyramid` session object before performing any
+actions in code which requires elevated privileges that is invoked via a form
+post. To use CSRF token support, you must enable a :term:`session factory`
+as described in :ref:`using_the_default_session_factory` or
+:ref:`using_alternate_session_factories`.
+
+Using the ``session.new_csrf_token`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To add a CSRF token to the session, use the ``session.new_csrf_token()`` method.
+
+.. code-block:: python
+
+ token = request.session.new_csrf_token()
+
+The ``new_csrf_token()`` method accepts no arguments. It returns a *token*
+string, which will be opaque and randomized. This token will also be set
+into the session, awaiting pickup by the ``session.get_csrf_token()`` method.
+You can subsequently use the returned token as the value of a hidden field in
+a form that posts to a method that requires elevated privileges. The handler
+for the form post should use ``session.get_csrf_token()`` (explained below) to
+obtain the current CSRF token related to the user from the session, and
+compare it to the value of the hidden form field.
+
+Using the ``session.get_csrf_token`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To get the current CSRF token from the session, use the
+``session.get_csrf_token()`` method.
+
+.. code-block:: python
+
+ token = request.session.get_csrf_token()
+
+The ``get_csrf_token()`` method accepts no arguments. It returns the "current"
+*token* string generated by the last call to ``session.new_csrf_token()``. You can
+then use it to compare against the token provided within form post hidden
+value data. For example, if your form rendering included the CSRF token
+obtained via ``session.new_csrf_token()`` as a hidden input field named
+``csrf_token()``:
+
+.. code-block:: python
+ :linenos:
+
+ token = request.session.get_csrf_token()
+ if token != request.POST['csrf_token']:
+ raise ValueError('CSRF token did not match')
+