哈希密码存储为BSON BinData Type

时间:2017-11-28 18:09:02

标签: mongodb python-3.x pymongo bson

我有这个脚本,这是一个将用户添加到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"
}

我想了解:

  • 为何将散列密码存储为BSON BinData?
  • 我可以避免这种情况吗?如果有可能,怎么样?
  • 之间有什么区别:
      

    直接存储dict X insert_one({"Username":var_name,"Password":var_hash})

1 个答案:

答案 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()的组合行为。