Skip to content

Commit

Permalink
Merge pull request #1325 from Flyguy/master
Browse files Browse the repository at this point in the history
The default charset for the basic http authentication is utf-8.
  • Loading branch information
davidism committed Nov 13, 2018
2 parents d22a029 + 0a748a2 commit 6e83117
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Expand Up @@ -84,6 +84,11 @@ Unreleased
using Flask you can use Flask-Caching. If you are using Werkzeug you
are welcome to extract the code (see LICENSE) into a separate
project. (`#1249`_)
- :func:`~http.parse_authorization_header` (and
:class:`~datastructures.Authorization`,
:attr:`~wrappers.Request.authorization`) treats the authorization
header as UTF-8. On Python 2, basic auth username and password are
``unicode``. (`#1325`_)

.. _`#209`: https://github.com/pallets/werkzeug/pull/209
.. _`#609`: https://github.com/pallets/werkzeug/pull/609
Expand Down Expand Up @@ -117,6 +122,7 @@ Unreleased
.. _`#1315`: https://github.com/pallets/werkzeug/pull/1315
.. _`#1316`: https://github.com/pallets/werkzeug/pull/1316
.. _`#1318`: https://github.com/pallets/werkzeug/pull/1318
.. _`#1325`: https://github.com/pallets/werkzeug/pull/1325
.. _`#1338`: https://github.com/pallets/werkzeug/pull/1338
.. _`#1340`: https://github.com/pallets/werkzeug/pull/1340
.. _`#1377`: https://github.com/pallets/werkzeug/pull/1377
Expand Down
14 changes: 12 additions & 2 deletions tests/test_http.py
Expand Up @@ -111,8 +111,18 @@ def test_cache_control_header(self):
def test_authorization_header(self):
a = http.parse_authorization_header('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==')
assert a.type == 'basic'
assert a.username == 'Aladdin'
assert a.password == 'open sesame'
assert a.username == u'Aladdin'
assert a.password == u'open sesame'

a = http.parse_authorization_header('Basic 0YDRg9GB0YHQutC40IE60JHRg9C60LLRiw==')
assert a.type == 'basic'
assert a.username == u'русскиЁ'
assert a.password == u'Буквы'

a = http.parse_authorization_header('Basic 5pmu6YCa6K+dOuS4reaWhw==')
assert a.type == 'basic'
assert a.username == u'普通话'
assert a.password == u'中文'

a = http.parse_authorization_header('''Digest username="Mufasa",
realm="testrealm@host.invalid",
Expand Down
14 changes: 12 additions & 2 deletions tests/test_wrappers.py
Expand Up @@ -206,8 +206,18 @@ def test_authorization_mixin():
})
a = request.authorization
strict_eq(a.type, 'basic')
strict_eq(a.username, 'Aladdin')
strict_eq(a.password, 'open sesame')
strict_eq(a.username, u'Aladdin')
strict_eq(a.password, u'open sesame')


def test_authorization_with_unicode():
request = wrappers.Request.from_values(headers={
'Authorization': 'Basic 0YDRg9GB0YHQutC40IE60JHRg9C60LLRiw=='
})
a = request.authorization
strict_eq(a.type, 'basic')
strict_eq(a.username, u'русскиЁ')
strict_eq(a.password, u'Буквы')


def test_stream_only_mixing():
Expand Down
9 changes: 7 additions & 2 deletions werkzeug/http.py
Expand Up @@ -41,6 +41,7 @@


_cookie_charset = 'latin1'
_basic_auth_charset = 'utf-8'
# for explanation of "media-range", etc. see Sections 5.3.{1,2} of RFC 7231
_accept_re = re.compile(
r'''( # media-range capturing-parenthesis
Expand Down Expand Up @@ -505,8 +506,12 @@ def parse_authorization_header(value):
username, password = base64.b64decode(auth_info).split(b':', 1)
except Exception:
return
return Authorization('basic', {'username': bytes_to_wsgi(username),
'password': bytes_to_wsgi(password)})
return Authorization(
'basic', {
'username': to_unicode(username, _basic_auth_charset),
'password': to_unicode(password, _basic_auth_charset)
}
)
elif auth_type == b'digest':
auth_map = parse_dict_header(auth_info)
for key in 'username', 'realm', 'nonce', 'uri', 'response':
Expand Down

0 comments on commit 6e83117

Please sign in to comment.