From db5e58e49f9a74965214b8d3dcafa6a36fd6be12 Mon Sep 17 00:00:00 2001 From: kelson Date: Wed, 19 Aug 2015 11:25:00 -0400 Subject: [PATCH] added HttpOnly cookies (default) added unit tests for cookie layout, secure cookies, and HttpOnly cookies Session.httponly_cookies=False to revert HttpOnly cookies --- gluon/globals.py | 12 ++++++--- gluon/tests/test_globals.py | 54 ++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/gluon/globals.py b/gluon/globals.py index 644a6b83..3fbe42ba 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -1023,10 +1023,16 @@ class Session(Storage): def _fixup_before_save(self): response = current.response rcookies = response.cookies - if self._forget and response.session_id_name in rcookies: + scookies = rcookies.get(response.session_id_name) + if not scookies: + return + if self._forget: del rcookies[response.session_id_name] - elif self._secure and response.session_id_name in rcookies: - rcookies[response.session_id_name]['secure'] = True + return + if self.get('httponly_cookies',True): + scookies['HttpOnly'] = True + if self._secure: + scookies['secure'] = True def clear_session_cookies(self): request = current.request diff --git a/gluon/tests/test_globals.py b/gluon/tests/test_globals.py index 5f9d5526..8ba6d4f0 100644 --- a/gluon/tests/test_globals.py +++ b/gluon/tests/test_globals.py @@ -11,9 +11,23 @@ from fix_path import fix_sys_path fix_sys_path(__file__) -from gluon.globals import Response +from gluon.globals import Request, Response, Session from gluon import URL +def setup_clean_session(): + request = Request(env={}) + request.application = 'a' + request.controller = 'c' + request.function = 'f' + request.folder = 'applications/admin' + response = Response() + session = Session() + session.connect(request, response) + from gluon.globals import current + current.request = request + current.response = response + current.session = session + return current class testResponse(unittest.TestCase): @@ -120,5 +134,43 @@ class testResponse(unittest.TestCase): content = return_includes(response) self.assertEqual(content, '') + def test_cookies(self): + current = setup_clean_session() + cookie = str(current.response.cookies) + session_key='%s=%s'%(current.response.session_id_name,current.response.session_id) + self.assertRegexpMatches(cookie, r'^Set-Cookie: ') + self.assertTrue(session_key in cookie) + self.assertTrue('Path=/' in cookie) + + def test_cookies_secure(self): + current = setup_clean_session() + current.session._fixup_before_save() + cookie = str(current.response.cookies) + self.assertTrue('secure' not in cookie) + + current = setup_clean_session() + current.session.secure() + current.session._fixup_before_save() + cookie = str(current.response.cookies) + self.assertTrue('secure' in cookie) + + def test_cookies_httponly(self): + current = setup_clean_session() + current.session._fixup_before_save() + cookie = str(current.response.cookies) + self.assertTrue('httponly' in cookie) + + current = setup_clean_session() + current.session.httponly_cookies = True + current.session._fixup_before_save() + cookie = str(current.response.cookies) + self.assertTrue('httponly' in cookie) + + current = setup_clean_session() + current.session.httponly_cookies = False + current.session._fixup_before_save() + cookie = str(current.response.cookies) + self.assertTrue('httponly' not in cookie) + if __name__ == '__main__': unittest.main()