我有这个脚本,这是一个将用户添加到mongo数据库的临时方法。
操作正常进行,但为密码生成的哈希值存储为BSON Binary Data (a.k.a BinData)。
#!/usr/bin/python3
import bcrypt
from getpass import getpass
from pymongo import MongoClient
def connect():
db_user = "mongo"
db_pass = "mongo"
db_addr = "127.0.0.1:27017"
uri = "mongodb://{0}:{1}@{2}".format(db_user,db_pass,db_addr)
client = MongoClient(uri,serverSelectionTimeoutMS=6000)
return client
try:
user_data = {}
user_data["Name"] = input("Full Name: ")
user_data["Sector"] = input("Sector: ")
user_data["Email"] = input("Email: ")
user_data["Username"] = input("Username: ")
password = getpass(prompt="Password: ").encode('utf-8')
salt = bcrypt.gensalt()
pass_hash = bcrypt.hashpw(password, salt)
user_data["Password"] = pass_hash
client = connect()
db = client.companydb
collection = db.Authentication
result = collection.insert_one(user_data)
print("Done!")
except Exception as e:
print("Exception:",e)
MongoDB的
> db.Authentication.find().pretty()
{
"_id" : ObjectId("5a1d9cf8e6023f20d3b11bf3"),
"Name" : "My Full Name",
"Password" : BinData(0,"JDJiJDEyJDR0RzFwRkNjaE1HdlExd0kuRXgyLk91U09yQWZYTWxZL2pZbUVod3N2NGhRR05XUXIyNDRh"),
"Username" : "ivanleoncz",
"Email" : "mymail@post.com",
"Sector" : "IT"
}
我想了解:
直接存储dict X
insert_one({"Username":var_name,"Password":var_hash})
?
答案 0 :(得分:1)
为什么将散列密码存储为BSON BinData?
这是因为bcrypt.hashpw()
返回bytes
数据类型。例如:
b'$2b$12$bvjnkItDoYvw.GUwBeVuwOuIxIQ5hUIx.ECovNrnYc1kgSP/kruXu'
同样在PyMongo(Python 3)中,字节将被编码为bson.binary.Binary(),反之亦然。
我可以避免这种情况吗?如果有可能,怎么样?
如果您打算在MongoDB中将字符串存储在字符串中,则可以在存储在字典中时对哈希进行解码。即
user_data["Password"] = pass_hash.decode("utf-8")
# When checking later you would have to encode it back to bytes.
bcrypt.checkpw(b"mysecretpassword", user_data["Password"].encode("utf-8"))
如评论中所述,关于仅存储密码和恢复密码以便稍后进行身份验证,您可以将其保留为二进制(除非您的用例需要它)
这是因为当从MongoDB中检索文档时,在Python 3中,bson.Binary的实例将直接解码回字节。您可以使用find()
检索文档来测试直接存储dict与insert_one
之间有什么区别吗?
从答案中可以看出,这是bcrypt.hashpw()
和insert_one()
的组合行为。