我已经看了所有与此相关的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
问题是从SQLAlchemy
String
列获取值并将其传递给bcrypt.checkpw
。String
用于Unicode字符串,它提供str
的值。但是bcrypt
只对字节字符串有效,所以它需要一个bytes
。这就是TypeError
所说的“在散列之前必须对Unicode对象进行编码”。在根据您使用的数据库后端和DB-API库(对于某些后端,还取决于数据库的配置方式),当您将}保存到}。在
bytes
值{String
列时,它可能会保存s.decode()
,在这种情况下,您可以使用user.password.encode()
来取回相同的字节,但可能不会。例如,它也可以保存,比如,str(s)
。在这种情况下,如果散列是bytes
值b'abcd'
,那么列值将是字符串"b'abcd'"
,因此调用encode
得到b"b'abcd'"
,而不是{处理这个问题的最干净的方法是使用
Binary
列1—或者更好的是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)
一样工作。相关问题 更多 >
编程相关推荐