Merge pull request #2716 from keitheis/quick_tutorial_hashpw_bcrypt
Add one-way password hash to security example in Quick Tutorial.
| | |
| | | - Jean-Christophe Bohin, 2016/06/13 |
| | | |
| | | - Jon Davidson, 2016/07/18 |
| | | |
| | | - Keith Yang, 2016/07/22 |
| | |
| | | .. code-block:: bash |
| | | |
| | | $ cd ..; cp -r view_classes authentication; cd authentication |
| | | |
| | | #. This step depends on bcrypt_, so add it as a dependency in |
| | | ``authentication/setup.py``: |
| | | |
| | | .. literalinclude:: authentication/setup.py |
| | | :linenos: |
| | | |
| | | #. Now we can activate the development-mode distribution: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pip install -e . |
| | | |
| | | #. Put the security hash in the ``authentication/development.ini`` |
| | |
| | | <authentication_module>` policy. We enabled it in our configuration and |
| | | provided a ticket-signing secret in our INI file. |
| | | |
| | | The function ``hash_password`` hashes user's password by bcrypt_ instead of |
| | | storing password in plain text directly as a best practice [1]_. And function |
| | | ``check_password`` will compare the hashed value of the submitted password |
| | | against the hashed value of the user's password. |
| | | |
| | | Our view class grew a login view. When you reached it via a ``GET`` request, it |
| | | returned a login form. When reached via ``POST``, it processed the submitted |
| | | username and password against the "groupfinder" callable that we registered in |
| | |
| | | |
| | | .. seealso:: See also :ref:`security_chapter`, |
| | | :ref:`AuthTktAuthenticationPolicy <authentication_module>`. |
| | | |
| | | .. _bcrypt: https://pypi.python.org/pypi/bcrypt |
| | | |
| | | .. [1] We are using the bcrypt_ package from PyPI to hash our passwords |
| | | securely. There are other one-way hash algorithms for passwords if |
| | | bcrypt is an issue on your system. Just make sure that it's an |
| | | algorithm approved for storing passwords versus a generic one-way hash. |
| | |
| | | |
| | | requires = [ |
| | | 'pyramid', |
| | | 'pyramid_chameleon' |
| | | 'pyramid_chameleon', |
| | | 'bcrypt' |
| | | ] |
| | | |
| | | setup(name='tutorial', |
| | |
| | | USERS = {'editor': 'editor', |
| | | 'viewer': 'viewer'} |
| | | import bcrypt |
| | | |
| | | |
| | | def hash_password(pw): |
| | | pwhash = bcrypt.hashpw(pw.encode('utf8'), bcrypt.gensalt()) |
| | | return pwhash.decode('utf8') |
| | | |
| | | def check_password(pw, hashed_pw): |
| | | expected_hash = hashed_pw.encode('utf8') |
| | | return bcrypt.checkpw(pw.encode('utf8'), expected_hash) |
| | | |
| | | |
| | | USERS = {'editor': hash_password('editor'), |
| | | 'viewer': hash_password('viewer')} |
| | | GROUPS = {'editor': ['group:editors']} |
| | | |
| | | |
| | |
| | | view_defaults |
| | | ) |
| | | |
| | | from .security import USERS |
| | | from .security import ( |
| | | USERS, |
| | | check_password |
| | | ) |
| | | |
| | | |
| | | @view_defaults(renderer='home.pt') |
| | |
| | | if 'form.submitted' in request.params: |
| | | login = request.params['login'] |
| | | password = request.params['password'] |
| | | if USERS.get(login) == password: |
| | | if check_password(password, USERS.get(login)): |
| | | headers = remember(request, login) |
| | | return HTTPFound(location=came_from, |
| | | headers=headers) |
| | |
| | | |
| | | requires = [ |
| | | 'pyramid', |
| | | 'pyramid_chameleon' |
| | | 'pyramid_chameleon', |
| | | 'bcrypt' |
| | | ] |
| | | |
| | | setup(name='tutorial', |
| | |
| | | USERS = {'editor': 'editor', |
| | | 'viewer': 'viewer'} |
| | | import bcrypt |
| | | |
| | | |
| | | def hash_password(pw): |
| | | pwhash = bcrypt.hashpw(pw.encode('utf8'), bcrypt.gensalt()) |
| | | return pwhash.decode('utf8') |
| | | |
| | | def check_password(pw, hashed_pw): |
| | | expected_hash = hashed_pw.encode('utf8') |
| | | return bcrypt.checkpw(pw.encode('utf8'), expected_hash) |
| | | |
| | | |
| | | USERS = {'editor': hash_password('editor'), |
| | | 'viewer': hash_password('viewer')} |
| | | GROUPS = {'editor': ['group:editors']} |
| | | |
| | | |
| | |
| | | forbidden_view_config |
| | | ) |
| | | |
| | | from .security import USERS |
| | | from .security import ( |
| | | USERS, |
| | | check_password |
| | | ) |
| | | |
| | | |
| | | @view_defaults(renderer='home.pt') |
| | |
| | | if 'form.submitted' in request.params: |
| | | login = request.params['login'] |
| | | password = request.params['password'] |
| | | if USERS.get(login) == password: |
| | | if check_password(password, USERS.get(login)): |
| | | headers = remember(request, login) |
| | | return HTTPFound(location=came_from, |
| | | headers=headers) |