A 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 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¶
In order to use sessions, you must set up a session factory during your Pyramid configuration.
A very basic, insecure sample session factory implementation is provided in the 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. This is suitable only for very small data sets.
It is digitally signed, however, and thus its data cannot easily be tampered with.
You can configure this session factory in your Pyramid
application by using the
session_factory argument to the
1 2 3 4 5
from pyramid.session import UnencryptedCookieSessionFactoryConfig my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet') from pyramid.config import Configurator config = Configurator(session_factory = my_session_factory)
Note the very long, very explicit name for
UnencryptedCookieSessionFactoryConfig. It’s trying to tell you that
this implementation is, by default, unencrypted. 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. And if you use this
sessioning implementation, and you inadvertently create a cross-site
scripting vulnerability in your application, because the session data is
stored unencrypted in a cookie, it will also be easier for evildoers to
obtain the current user’s cross-site scripting token. In short, 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”, and you are sure your application has no
cross-site scripting vulnerabilities.
Using a Session Object¶
Once a session factory has been configured for your application, you
can access session objects provided by the session factory via
session attribute of any request object. For
1 2 3 4 5 6 7 8 9 10 11
from pyramid.response 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 dictionary methods, along with some extra attributes, and methods.
- An integer timestamp indicating the time that this session was created.
- A boolean. If
newis True, this session is new. Otherwise, it has been constituted from data that was already serialized.
- Call this when you mutate a mutable value in the session namespace. See the gotchas below for details on when, and why you should call this.
- 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
- Keys and values of session data must be pickleable. This means, 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.
- 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
changed()method of the session object. In this case, the session has no way to know that is was modified. However, when you modify a session object directly, such as setting a value (i.e.,
__setitem__), or removing a key (e.g.,
pop), the session will automatically know that it needs to re-serialize its data, thus calling
changed()is unnecessary. There is no harm in calling
changed()in either case, so when in doubt, call it after you’ve changed sessioning data.
Using Alternate Session Factories¶
At the time of this writing, exactly one alternate session factory
implementation exists, named
pyramid_beaker. This is a session factory
that uses the Beaker library as a backend.
Beaker has support for file-based sessions, database based sessions, and
encrypted cookie-based sessions. See the pyramid_beaker documentation for more
Creating Your Own Session Factory¶
If none of the default or otherwise available sessioning
implementations for Pyramid suit you, you may create your own
session object by implementing a session factory. Your
session factory should return a session. The interfaces for
both types are available in
pyramid.interfaces.ISession. You might use the cookie
implementation in the
pyramid.session module as inspiration.
“Flash messages” are simply a queue of message strings stored in the session. To use flash messaging, you must enable a session factory as described in Using The Default Session Factory or 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 session object.
To add a message to a flash message queue, use a session object’s
flash() method appends a message to a flash queue, creating the queue
flash() accepts three arguments:
flash(message, queue='', allow_duplicate=True)¶
message argument is required. It represents a message you wish to
later display to a user. It is usually a string but the
provide is not modified in any way.
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
queue defaults to the
empty string. The empty string represents the default flash message
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.
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
pop_flash() method. This returns a list of the messages
that were added to the flash queue, and empties the queue.
1 2 3
>>> request.session.flash('info message') >>> request.session.pop_flash() ['info message']
session.pop_flash() again like above without a corresponding call
session.flash() will return an empty list, because the queue has already
1 2 3 4 5
>>> request.session.flash('info message') >>> request.session.pop_flash() ['info message'] >>> request.session.pop_flash() 
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.
1 2 3 4 5 6 7 8 9
>>> 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() 
Preventing Cross-Site Request Forgery Attacks¶
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 secretly 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 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 session factory as described in Using The Default Session Factory or Using Alternate Session Factories.
To get the current CSRF token from the session, use the
token = request.session.get_csrf_token()
session.get_csrf_token() method accepts no arguments. It returns a
CSRF token string. If
session.new_csrf_token() was invoked previously for this session, the
existing token will be returned. If no CSRF token previously existed for
this session, a new token will be will be set into the session and returned.
The newly created token will be opaque and randomized.
You can 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() again to obtain the
current CSRF token related to the user from the session, and compare it to
the value of the hidden form field. For example, if your form rendering
included the CSRF token obtained via
session.get_csrf_token() as a hidden
input field named
1 2 3
token = request.session.get_csrf_token() if token != request.POST['csrf_token']: raise ValueError('CSRF token did not match')
To explicitly add a new CSRF token to the session, use the
session.new_csrf_token() method. This differs only from
session.get_csrf_token() inasmuch as it clears any existing CSRF token,
creates a new CSRF token, sets the token into the session, and returns the
token = request.session.new_csrf_token()