diff options
| -rw-r--r-- | docs/api/session.rst | 2 | ||||
| -rw-r--r-- | docs/whatsnew-1.4.rst | 17 | ||||
| -rw-r--r-- | pyramid/session.py | 16 | ||||
| -rw-r--r-- | pyramid/tests/test_session.py | 20 |
4 files changed, 48 insertions, 7 deletions
diff --git a/docs/api/session.rst b/docs/api/session.rst index 44b4bd860..31bc196ad 100644 --- a/docs/api/session.rst +++ b/docs/api/session.rst @@ -11,4 +11,6 @@ .. autofunction:: signed_deserialize + .. autofunction:: check_csrf_token + diff --git a/docs/whatsnew-1.4.rst b/docs/whatsnew-1.4.rst index f57178db1..76320f6e6 100644 --- a/docs/whatsnew-1.4.rst +++ b/docs/whatsnew-1.4.rst @@ -94,10 +94,10 @@ Minor Feature Additions - :meth:`pyramid.config.Configurator.add_request_method` has been introduced to support extending request objects with arbitrary callables. This method - expands on the previous + expands on the now documentation-deprecated :meth:`pyramid.config.Configurator.set_request_property` by supporting - methods as well as properties. This method causes less code to be executed - at request construction time than + methods as well as properties. This method also causes less code to be + executed at request construction time than :meth:`~pyramid.config.Configurator.set_request_property`. - The static view machinery now raises rather than returns @@ -133,13 +133,13 @@ Minor Feature Additions ``pyramid.util.InstancePropertyMixin`` class such as ``set_property``. - Request properties and methods added via - :meth:`pyramid.config.Configurator.set_request_property` or - :meth:`pyramid.config.Configurator.add_request_method` are now available to + :meth:`pyramid.config.Configurator.add_request_method` or + :meth:`pyramid.config.Configurator.set_request_property` are now available to tweens. - Request properties and methods added via - :meth:`pyramid.config.Configurator.set_request_property` or - :meth:`pyramid.config.Configurator.add_request_method` are now available + :meth:`pyramid.config.Configurator.add_request_method` or + :meth:`pyramid.config.Configurator.set_request_property` are now available in the request object returned from :func:`pyramid.paster.bootstrap`. - ``request.context`` of environment request during @@ -153,6 +153,9 @@ Minor Feature Additions used to generate a configurator in a test, e.g. ``with testing.testConfig(...):``. +- A new :func:`pyramid.session.check_csrf_token` convenience API function was + added. + Backwards Incompatibilities --------------------------- diff --git a/pyramid/session.py b/pyramid/session.py index 40e21ddbc..3f700564d 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -15,6 +15,7 @@ from pyramid.compat import ( native_, ) +from pyramid.httpexceptions import HTTPBadRequest from pyramid.interfaces import ISession from pyramid.util import strings_differ @@ -80,6 +81,21 @@ def signed_deserialize(serialized, secret, hmac=hmac): return pickle.loads(pickled) +def check_csrf_token(request, token='csrf_token'): + """ Check the CSRF token in the request's session against the value in + ``request.params.get(token)``. If ``token`` is not supplied, the string + value ``csrf_token`` will be used as the token value. If the value in + ``request.params.get(token)`` doesn't match the value supplied by + ``request.session.get_csrf_token()``, this function will raise an + :exc:`pyramid.httpexceptions.HTTPBadRequest` exception. If the CSRF + check is successful, this function will return ``True``. + + .. versionadded:: 1.4a2 + """ + if request.params.get(token) != request.session.get_csrf_token(): + raise HTTPBadRequest('incorrect CSRF token') + return True + def UnencryptedCookieSessionFactoryConfig( secret, timeout=1200, diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py index 5143b7a95..21cf16b12 100644 --- a/pyramid/tests/test_session.py +++ b/pyramid/tests/test_session.py @@ -355,6 +355,26 @@ class Test_signed_deserialize(unittest.TestCase): serialized = 'bad' + serialize('123', 'secret') self.assertRaises(ValueError, self._callFUT, serialized, 'secret') +class Test_check_csrf_token(unittest.TestCase): + def _callFUT(self, request, token): + from ..session import check_csrf_token + return check_csrf_token(request, token) + + def test_success(self): + request = testing.DummyRequest() + request.params['csrf_token'] = request.session.get_csrf_token() + self.assertEqual(self._callFUT(request, 'csrf_token'), True) + + def test_success_default_token(self): + from ..session import check_csrf_token + request = testing.DummyRequest() + request.params['csrf_token'] = request.session.get_csrf_token() + self.assertEqual(check_csrf_token(request), True) + + def test_failure(self): + from pyramid.httpexceptions import HTTPBadRequest + request = testing.DummyRequest() + self.assertRaises(HTTPBadRequest, self._callFUT, request, 'csrf_token') class DummySessionFactory(dict): _dirty = False |
