diff options
| author | Steve Piercy <web@stevepiercy.com> | 2015-10-16 05:14:07 -0700 |
|---|---|---|
| committer | Steve Piercy <web@stevepiercy.com> | 2015-10-16 05:14:07 -0700 |
| commit | 07c3e16447e960f1d545c40a2b1ef0830cdbcd14 (patch) | |
| tree | 6d2726b650ca209e94a8895f47cc76f9f1815548 | |
| parent | 5a49b5537916ad28a70776ab8728b6e885d8a188 (diff) | |
| parent | 42049eb25d91a45d46f581a18d82a91b63470290 (diff) | |
| download | pyramid-07c3e16447e960f1d545c40a2b1ef0830cdbcd14.tar.gz pyramid-07c3e16447e960f1d545c40a2b1ef0830cdbcd14.tar.bz2 pyramid-07c3e16447e960f1d545c40a2b1ef0830cdbcd14.zip | |
Merge pull request #1994 from stevepiercy/master
minor grammar, rewrap 79 cols
| -rw-r--r-- | docs/narr/sessions.rst | 239 |
1 files changed, 113 insertions, 126 deletions
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 916c6c1f6..db554a93b 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -6,45 +6,44 @@ 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. +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. +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. .. index:: single: session factory (default) .. _using_the_default_session_factory: -Using The Default Session Factory +Using the Default Session Factory --------------------------------- -In order to use sessions, you must set up a :term:`session factory` -during your :app:`Pyramid` configuration. +In order to use sessions, you must set up a :term:`session factory` during your +:app:`Pyramid` configuration. -A very basic, insecure sample session factory implementation is -provided in the :app:`Pyramid` core. It uses a cookie to store -session information. This implementation has the following -limitations: +A very basic, insecure sample session factory implementation is provided in the +:app:`Pyramid` core. It uses a cookie to store session information. This +implementation has the following limitations: -- 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 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. +- 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. +It is digitally signed, however, and thus its data cannot easily be tampered +with. -You can configure this session factory in your :app:`Pyramid` application -by using the :meth:`pyramid.config.Configurator.set_session_factory` method. +You can configure this session factory in your :app:`Pyramid` application by +using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. code-block:: python :linenos: @@ -59,17 +58,17 @@ by using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. warning:: By default the :func:`~pyramid.session.SignedCookieSessionFactory` - implementation is *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 + implementation is *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. .. index:: @@ -78,10 +77,9 @@ by using the :meth:`pyramid.config.Configurator.set_session_factory` method. 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 -the ``session`` attribute of any :term:`request` object. For -example: +Once a session factory has been configured for your application, you can access +session objects provided by the session factory via the ``session`` attribute +of any :term:`request` object. For example: .. code-block:: python :linenos: @@ -98,13 +96,12 @@ example: else: return Response('Fred was not in the session') -The first time this view is invoked produces ``Fred was not in the -session``. Subsequent invocations produce ``Fred was in the -session``, assuming of course that the client side maintains the -session's identity across multiple requests. +The first time this view is invoked produces ``Fred was not in the session``. +Subsequent invocations produce ``Fred was in the session``, assuming of course +that the client side maintains the session's identity across multiple requests. You can use a session much like a Python dictionary. It supports all -dictionary methods, along with some extra attributes, and methods. +dictionary methods, along with some extra attributes and methods. Extra attributes: @@ -112,42 +109,39 @@ Extra attributes: 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. + 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. - See the gotchas below for details on when, and why you should - call this. + 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. ``invalidate()`` - Call this when you want to invalidate the session (dump all data, - and -- perhaps -- set a clearing cookie). + 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. +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 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 - call the ``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., ``del`` or ``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. +- 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 call the + ``changed()`` method of the session object. In this case, the session has no + way to know that it was modified. However, when you modify a session object + directly, such as setting a value (i.e., ``__setitem__``), or removing a key + (e.g., ``del`` or ``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. .. index:: single: pyramid_redis_sessions @@ -183,14 +177,13 @@ pyramid_beaker_ Beaker_ Session factory for Pyramid Creating Your Own Session Factory --------------------------------- -If none of the default or otherwise available sessioning -implementations for :app:`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 +If none of the default or otherwise available sessioning implementations for +:app:`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. +:class:`pyramid.interfaces.ISession`. You might use the cookie implementation +in the :mod:`pyramid.session` module as inspiration. .. index:: single: flash messages @@ -205,9 +198,9 @@ Flash Messages 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 +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. @@ -235,22 +228,21 @@ 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. +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. +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. .. index:: single: session.pop_flash @@ -259,12 +251,12 @@ 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. +``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. +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='') @@ -288,10 +280,10 @@ been popped. 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. +Once one or more messages have 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='') @@ -322,8 +314,8 @@ You can avoid most of these attacks by issuing a unique token to the browser and then requiring that it be present in all potentially unsafe requests. :app:`Pyramid` sessions provide facilities to create and check CSRF tokens. -To use CSRF tokens, you must first enable a :term:`session factory` -as described in :ref:`using_the_default_session_factory` or +To use CSRF tokens, you must first enable a :term:`session factory` as +described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. .. index:: @@ -342,9 +334,9 @@ To get the current CSRF token from the session, use the The ``session.get_csrf_token()`` method accepts no arguments. It returns a CSRF *token* string. If ``session.get_csrf_token()`` or ``session.new_csrf_token()`` was invoked previously for this session, then the -existing token will be returned. If no CSRF token previously existed for -this session, then a new token will be will be set into the session and returned. -The newly created token will be opaque and randomized. +existing token will be returned. If no CSRF token previously existed for this +session, then a new token 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, or supply it as a request @@ -359,7 +351,7 @@ For example, include the CSRF token as a hidden field: <input type="submit" value="Delete Everything"> </form> -Or, include it as a header in a jQuery AJAX request: +Or include it as a header in a jQuery AJAX request: .. code-block:: javascript @@ -372,18 +364,17 @@ Or, include it as a header in a jQuery AJAX request: alert("Deleted"); }); - -The handler for the URL that receives the request -should then require that the correct CSRF token is supplied. +The handler for the URL that receives the request should then require that the +correct CSRF token is supplied. Checking CSRF Tokens Manually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In request handling code, you can check the presence and validity of a CSRF -token with :func:`pyramid.session.check_csrf_token`. If the token is -valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``. -Optionally, you can specify ``raises=False`` to have the check return ``False`` -instead of raising an exception. +token with :func:`pyramid.session.check_csrf_token`. If the token is valid, it +will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally, +you can specify ``raises=False`` to have the check return ``False`` instead of +raising an exception. By default, it checks for a GET or POST parameter named ``csrf_token`` or a header named ``X-CSRF-Token``. @@ -401,12 +392,12 @@ header named ``X-CSRF-Token``. .. index:: single: session.new_csrf_token -Checking CSRF Tokens With A View Predicate +Checking CSRF Tokens with a View Predicate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A convenient way to require a valid CSRF Token for a particular view is to -include ``check_csrf=True`` as a view predicate. -See :meth:`pyramid.config.Configurator.add_view`. +A convenient way to require a valid CSRF token for a particular view is to +include ``check_csrf=True`` as a view predicate. See +:meth:`pyramid.config.Configurator.add_view`. .. code-block:: python @@ -415,23 +406,19 @@ See :meth:`pyramid.config.Configurator.add_view`. ... .. note:: - A mismatch of CSRF token is treated like any other predicate miss, and the + A mismatch of a CSRF token is treated like any other predicate miss, and the predicate system, when it doesn't find a view, raises ``HTTPNotFound`` instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different from calling :func:`pyramid.session.check_csrf_token`. - Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To explicitly create a new CSRF token, 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. +To explicitly create a new CSRF token, 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. .. code-block:: python token = request.session.new_csrf_token() - - |
