我正在尝试在我的应用中使用散列密码,如下所示:
class UserService():
def register_user(self, username, email, password):
if self.__checkIfUserExists(username) is True:
return False
else:
hashed_password = self.__hash_password(password.encode('utf-8'), bcrypt.gensalt())
user = User(username=username, email=email, password_hash=hashed_password)
db.session.add(user)
db.session.commit()
db.session.close()
return True
def authenticate_user(self, email, password):
user = User.query.filter_by(email=email).first()
hashed_pw = self.__hash_password(password.encode("utf-8"), bcrypt.gensalt())
print(hashed_pw == user.password_hash)
if user and hashed_pw == user.password_hash:
return True
return False
def __checkIfUserExists(self, username):
exists = db.session.query(db.exists().where(User.username== username)).scalar()
return exists
def __hash_password(self, password, salt):
return bcrypt.hashpw(password, salt)
嗯,密码永远不会匹配。
我如何让它工作?我的错误在哪里?我以为我必须将提供的密码的哈希值与数据库中存储的哈希值进行比较..?
答案 0 :(得分:3)
来自https://pypi.python.org/pypi/bcrypt/2.0.0:
>>> import bcrypt
>>> password = b"super secret password"
>>> # Hash a password for the first time, with a randomly-generated salt
>>> hashed = bcrypt.hashpw(password, bcrypt.gensalt())
>>> # Check that a unhashed password matches one that has previously been
>>> # hashed
>>> if bcrypt.hashpw(password, hashed) == hashed:
... print("It Matches!")
... else:
... print("It Does not Match :(")
请注意hashpw
接受盐或以前的哈希密码(包括用于创建它的盐),以便进行适当的比较。
您已使用bcrypt.gensalt()
两次,这会产生两种不同的随机盐,因此散列会有所不同。
答案 1 :(得分:0)
从版本3.1.0开始,已添加checkpw。
要保持pythonic,您可以使用checkpw而不是再次与哈希密码进行比较。
>>> import bcrypt
>>> password= 'cantguessme'
>>>hashed= bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(12))
>>>if bcrypt.checkpw(password, hashed):
... print("Yaay, It Matches!")
... else:
... print("Oops, It Does not Match :(")
答案 2 :(得分:0)
此答案可能对使用 DB 保存加密密码的人有所帮助。
问题:我将编码后的密码保存到字符串列中。
解决方案:散列密码是二进制类型,必须保存为二进制,而不是字符串或 JSON。
我的代码中密码列的列属性,我在这里使用了 Postgresql、Flask 和 sqlalchemy,它们在我更改列数据类型后起作用
from sqlalchemy import Column, String, Integer, Boolean, Date, LargeBinary
from db import Base
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
userId = Column(String(50), nullable=False)
firstName = Column(String(50), nullable=False)
password = Column(LargeBinary(100), nullable=False)
recovery = Column(String(25))
phone = Column(String(10), nullable=False, unique=True)
phoneVerified = Column(Boolean, nullable=False)
email = Column(String(50), nullable=False, unique=True)
emailVerified = Column(Boolean, nullable=False)
def __init__(self, userId, firstName, password, phone, phoneVerified, email, emailVerified, recovery):
self.userId = userId
self.firstName = firstName
self.password = password
self.phone = phone
self.email = email
self.phoneVerified = phoneVerified
self.emailVerified = emailVerified
self.recovery = recovery
资源代码:
import bcrypt
import shortuuid
from flask_restful import Resource, reqparse
from entities.User import User
class Register(Resource):
@staticmethod
def post():
data = Register.parser.parse_args()
hashed = bcrypt.hashpw(data.password.encode('utf-8'), bcrypt.gensalt())
user = User(userId=shortuuid.ShortUUID().random(length=10), firstName=data.firstName,
password=hashed, phone=data.phone, phoneVerified=False, email=data.email,
emailVerified=False, recovery=shortuuid.ShortUUID().random(length=25))
session.add(user)
session.commit()
session.close()
return {'description': 'You are registered'}, 201
class Login(Resource):
@staticmethod
def post():
data = Login.parser.parse_args()
user = find_by_email(data.email)
if user:
pw_check = bcrypt.checkpw(password=data.password.encode('utf-8'), hashed_password=user.password)
access_token = create_access_token(identity=user.id, fresh=True)
refresh_token = create_refresh_token(identity=user.id)
return {'access_token': access_token, 'refresh_token': refresh_token}, 200
return {'description': 'Invalid credentials'}, 401