Bcrypt Hash返回TypeError(“在散列之前必须对Unicodeobjects进行编码”)并且无效

2024-06-06 05:08:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经看了所有与此相关的StackOverflow问题,但我似乎不明白这一点。当我散列密码并对照密码本身进行检查时,它会使用当前代码返回TypeError“Unicode objects must be encoded before hash”:

from scripts import tabledef
from flask import session
from sqlalchemy.orm import sessionmaker
from contextlib import contextmanager
import bcrypt

(Unrelated Python code...)

def hash_password(password):
     return bcrypt.hashpw(password.encode('utf8'), bcrypt.gensalt())


def credentials_valid(username, password):
    with session_scope() as s:
        user = s.query(tabledef.User).filter(
            tabledef.User.username.in_([username])).first()
        if user:

            return bcrypt.checkpw(password.encode('utf8'), user.password)
        else:
            return False

当我试图通过设置user.password= user.password.encode('utf8')来修复这个错误时,我得到“Invalid Salt”。在

这个代码有什么问题?在

更新: 我通过用户输入的烧瓶来存储密码:

^{pr2}$

这是我得到的错误:

/lib/python3.5/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/env/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/env/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/env/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/Flaskex-master/app.py", line 34, in login
    if helpers.credentials_valid(username, password):
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/Flaskex-master/scripts/helpers.py", line 64, in credentials_valid
    return bcrypt.checkpw(password.encode('utf8'), user.password)
  File "/home/suraj/Documents/Programming/current-projects/GW_Dining_Tracker/env/lib/python3.5/site-packages/bcrypt/__init__.py", line 101, in checkpw
    raise TypeError("Unicode-objects must be encoded before checking")
TypeError: Unicode-objects must be encoded before checking

Tags: inpyhomelinepasswordcurrentdocumentsfile
1条回答
网友
1楼 · 发布于 2024-06-06 05:08:31

问题是从SQLAlchemy String列获取值并将其传递给bcrypt.checkpwString用于Unicode字符串,它提供str的值。但是bcrypt只对字节字符串有效,所以它需要一个bytes。这就是TypeError所说的“在散列之前必须对Unicode对象进行编码”。在

根据您使用的数据库后端和DB-API库(对于某些后端,还取决于数据库的配置方式),当您将bytes值{}保存到String列时,它可能会保存s.decode(),在这种情况下,您可以使用user.password.encode()来取回相同的字节,但可能不会。例如,它也可以保存,比如,str(s)。在这种情况下,如果散列是bytesb'abcd',那么列值将是字符串"b'abcd'",因此调用encode得到b"b'abcd'",而不是{}。在

处理这个问题的最干净的方法是使用Binary1—或者更好的是Binary(60)2—来存储散列,而不是String列。任何支持Binary的DB-API都将按原样存储bytes,并将其返回为bytes,这正是您想要的。在


1。Binary是可选类型。如果您的DB-ABI中没有它,则可以使用相同的类型BINARY。如果不是,请查看the list of types,并尝试从_Binary继承的其他类型。名字或首字母缩略词中没有“large”的词可能会更有效,但除此之外,它们中的任何一个都应该有效。

2。在默认设置下,bcrypt可打印摘要始终为60字节。数据库通常可以更紧凑地存储固定宽度的字段,如BINARY(60),并且比VARBINARY这样的可变宽度字段更快地进行搜索。仅仅使用普通的BINARY可能是好的,但是它也可能像VARBINARY一样工作,或者可能浪费空间并像BINARY(255)一样工作。

相关问题 更多 >