diff options
| -rw-r--r-- | docs/api/session.rst | 2 | ||||
| -rw-r--r-- | docs/whatsnew-1.4.rst | 3 | ||||
| -rw-r--r-- | pyramid/session.py | 16 | ||||
| -rw-r--r-- | pyramid/tests/test_session.py | 20 |
4 files changed, 41 insertions, 0 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..fc25c415e 100644 --- a/docs/whatsnew-1.4.rst +++ b/docs/whatsnew-1.4.rst @@ -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 |
