From 76e95124632a98bea84d4d81a5e0b322d56806fa Mon Sep 17 00:00:00 2001 From: Tres Seaver <tseaver@agendaless.com> Date: Tue, 13 Jul 2010 18:29:12 +0200 Subject: [PATCH] Make the InsecureCookiePlugin take a ``charset`` argument --- docs/plugins.rst | 7 ++- repoze/who/plugins/cookie.py | 19 +++++++-- repoze/who/plugins/tests/test_cookie.py | 43 +++++++++++++++++++-- CHANGES.txt | 4 ++ 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ac5a72c..5db21d0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,10 @@ After 2.0a2 (unreleased) ----------------------- +- Make the ``repoze.who.plugins.cookie.InsecureCookiePlugin`` take a + ``charset`` argument, and use to to encode / decode login and password. + See http://bugs.repoze.org/issue155 + - In ``repoze.who.restrict``, return headers as a list, to keep ``wsgiref`` from complaining. diff --git a/docs/plugins.rst b/docs/plugins.rst index 4b57564..d155397 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -108,9 +108,12 @@ A :class:`InsecureCookiePlugin` is an ``IIdentifier`` plugin. It stores identification information in an insecure form (the base64 value of the username and password separated by a colon) in a - client-side cookie. It accepts a single argument named + client-side cookie. It accepts a single required argument named *cookie_name*. This is the cookie name of the cookie used to store - the identification information. + the identification information. The plugin also accepts two optional + arguments: *cookie_path* is the URL path root which scopes the cookie, + and *charset* is the name of a codec used to convert the login and password + to and from unicode. .. module:: repoze.who.plugins.form diff --git a/repoze/who/plugins/cookie.py b/repoze/who/plugins/cookie.py index 3280ac6..b6945a1 100644 --- a/repoze/who/plugins/cookie.py +++ b/repoze/who/plugins/cookie.py @@ -10,9 +10,10 @@ implements(IIdentifier) - def __init__(self, cookie_name, cookie_path='/'): + def __init__(self, cookie_name, cookie_path='/', charset=None): self.cookie_name = cookie_name self.cookie_path = cookie_path + self.charset = charset # IIdentifier def identify(self, environ): @@ -29,6 +30,9 @@ try: login, password = auth.split(':', 1) + if self.charset is not None: + login = login.decode(self.charset) + password = password.decode(self.charset) return {'login':login, 'password':password} except ValueError: # not enough values to unpack return None @@ -42,7 +46,12 @@ # IIdentifier def remember(self, environ, identity): - cookie_value = '%(login)s:%(password)s' % identity + login = identity['login'] + password = identity['password'] + if self.charset is not None: + login = login.encode(self.charset) + password = password.encode(self.charset) + cookie_value = '%s:%s' % (login, password) cookie_value = cookie_value.encode('base64').rstrip() cookies = get_cookies(environ) existing = cookies.get(self.cookie_name) @@ -57,7 +66,9 @@ return '<%s %s>' % (self.__class__.__name__, id(self)) #pragma NO COVERAGE -def make_plugin(cookie_name='repoze.who.plugins.cookie', cookie_path='/'): - plugin = InsecureCookiePlugin(cookie_name, cookie_path) +def make_plugin(cookie_name='repoze.who.plugins.cookie', + cookie_path='/', + charset=None): + plugin = InsecureCookiePlugin(cookie_name, cookie_path, charset) return plugin diff --git a/repoze/who/plugins/tests/test_cookie.py b/repoze/who/plugins/tests/test_cookie.py index 74e3a54..cba2545 100644 --- a/repoze/who/plugins/tests/test_cookie.py +++ b/repoze/who/plugins/tests/test_cookie.py @@ -49,6 +49,16 @@ result = plugin.identify(environ) self.assertEqual(result, {'login':'foo', 'password':'password'}) + def test_identify_encoded(self): + LOGIN = 'tr\xc3\xa9sbien' # UTF-8 encoded e-acute + PASSWORD = 'p\xc3\x80ssword' # UTF-8 encoded capital A grave + plugin = self._makeOne('oatmeal', charset='utf-8') + auth = ('%s:%s' % (LOGIN, PASSWORD)).encode('base64').rstrip() + environ = self._makeEnviron({'HTTP_COOKIE':'oatmeal=%s;' % auth}) + result = plugin.identify(environ) + self.assertEqual(result, {'login': LOGIN.decode('utf8'), + 'password': PASSWORD.decode('utf8')}) + def test_remember_creds_same(self): plugin = self._makeOne('oatmeal') creds = {'login':'foo', 'password':'password'} @@ -68,10 +78,17 @@ expected = 'oatmeal=%s; Path=/;' % creds_auth self.assertEqual(result, [('Set-Cookie', expected)]) - def test_factory(self): - from repoze.who.plugins.cookie import make_plugin - plugin = make_plugin('foo') - self.assertEqual(plugin.cookie_name, 'foo') + def test_remember_encoded(self): + LOGIN = 'tr\xc3\xa9sbien' # UTF-8 encoded e-acute + PASSWORD = 'p\xc3\x80ssword' # UTF-8 encoded capital A grave + plugin = self._makeOne('oatmeal', charset='utf-8') + creds = {'login': LOGIN.decode('utf8'), + 'password': PASSWORD.decode('utf8')} + creds_auth = ('%s:%s' % (LOGIN, PASSWORD)).encode('base64').rstrip() + environ = self._makeEnviron() + result = plugin.remember(environ, creds) + expected = 'oatmeal=%s; Path=/;' % creds_auth + self.assertEqual(result, [('Set-Cookie', expected)]) def test_forget(self): plugin = self._makeOne('oatmeal') @@ -82,3 +99,21 @@ self.assertEqual(name, 'Set-Cookie') self.assertEqual(value, 'oatmeal=""; Path=/; Expires=Sun, 10-May-1971 11:59:00 GMT') + + def test_factory(self): + from repoze.who.plugins.cookie import make_plugin + plugin = make_plugin('foo') + self.assertEqual(plugin.cookie_name, 'foo') + self.assertEqual(plugin.charset, None) + + def test_factory_with_cookie_path(self): + from repoze.who.plugins.cookie import make_plugin + plugin = make_plugin('foo', '/bar') + self.assertEqual(plugin.cookie_name, 'foo') + self.assertEqual(plugin.cookie_path, '/bar') + + def test_factory_with_charset(self): + from repoze.who.plugins.cookie import make_plugin + plugin = make_plugin('foo', charset='utf8') + self.assertEqual(plugin.cookie_name, 'foo') + self.assertEqual(plugin.charset, 'utf8') -- Gitblit v1.9.3