Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKen Alger
Treehouse Teacher[SOLVED] Python, and Flask, and Bcrypt, oh my!
Attempting to verify passwords with Flask and Bcrypt. Cannot use flask.ext.bcrypt
because of a lack of a Visual Studio 2010 component on my system, so I am just using bcrypt
.
I am saving the password to a database and in doing so am having to encode it otherwise I get a TypeError: Unicode-objects must be encoded before hashing
. Code would be similar to:
import bcrypt
import datetime
from flask.ext.login import UserMixin
from peewee import *
from playhouse.postgres_ext import PostgresqlExtDatabase
DATABASE = PostgresqlExtDatabase(database='leaderboard', user='postgres')
ROUNDS = 5 # Number of hash rounds, set low for development, increase for production
class BaseModel(Model):
class Meta:
database = DATABASE
class User(UserMixin, BaseModel):
email = CharField(unique=True)
password = CharField(max_length=100)
joined_at = DateTimeField(default=datetime.datetime.now)
class Meta:
order_by = ('joined_at',)
@classmethod
def create_user(cls, email, password):
try:
with DATABASE.transaction():
cls.create(
email=email,
password=bcrypt.hashpw(password.encode('utf-8', bcrypt.gensalt(ROUNDS))
)
except IntegrityError:
raise ValueError("Sorry, user already exists.")
def initialize():
DATABASE.connect()
DATABASE.create_tables([User], safe=True)
DATABASE.close()
That seems to work just fine as long as I include the encode('utf-8')
.
from flask.ext.wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import (DataRequired, Email)
class LoginForm(Form):
"""The form for logging into the site"""
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
With me so far?
Now, in my application when I go to check the password in the form against the database I have:
if bcrypt.hashpw(form.password.data, student.password) == student.password:
Wham! Back to my TypeError from before. My question then, and perhaps Kenneth Love would be so kind as to shed some light on the subject, is when and where is bcrypt expecting encoding to occur and, more importantly, how can I verify my passwords?
Any help is very much appreciated.
Ken
3 Answers
Ken Alger
Treehouse TeacherSorry for dropping this thread guys, I'll attempt to recall what I did, but if what I post isn't working for you, please bear with me and we can work through it together, okay?
1) I included hashpw
from bcrypt
:
from bcrypt import hashpw
2) In my route I changed by password check to (tabs not accurate in snippet):
if student.password == hashpw(form.password.data.encode('UTF_8'),
student.password.encode('UTF_8')).decode():
If memory serves the way the hashing works with UTF-8
requires those encode()
methods and then the decode()
pops it back out to be able to do the equality check. Took me quite a bit of searching to figure it out and even longer playing with various orders of encoding and decoding and where to have the UTF-8
. Kind of was one of those "Holly cow, that worked!" moments when it finally worked.
Post back with other questions. I'll try to be more responsive than 4 or 5 months.
Happy coding,
Ken
Chris Freeman
Treehouse Moderator 68,454 PointsI was also getting Unicode-objects must be encoded before hashing
errors. I was most curious about how thing worked in the Workspace but not locally. I downloaded a workspace and it failed locally. I figured it was an environment problem. bcrypt
was not working for me.
In the workspace I ran the command:
$ pip freeze > requirements.txt
Looking at this file, I did not see bcrypt
. Instead, there was py-bcrypt
! So uninstalled bcrypt
and its dependents:
# No longer needed
$ pip uninstall bcripyt
$ pip uninstall cff8
$ pip uninstall pycparcer
# get py-bcrypt
$ pip install py-bcrypt
Then everything worked as expected. No need to add .encode()
to passwords, From scratch, I was able to run flask locally using my answer to How to run flask locally
Ken Alger
Treehouse TeacherNever mind, I was able to figure it out.
Andrew Hill
8,934 PointsWhat was your solution? I am running into the same problem.
Chris Freeman
Treehouse Moderator 68,454 Points2nd: what was your solution?
Chris Freeman
Treehouse Moderator 68,454 PointsAndrew Hill: Are you trying to run outside of the Workspaces? What environment are you using?
Ken Alger: Were you also trying to work outside of Workspaces? Are you on Windows?
I have been trying to run the examples (as typed by Kenneth, no from workspaces) on Ubuntu 14.04. I may have solved it, but I wanted to check in with both of you on your environments.
Thanks.