python flask-security: 加密错误“无法识别哈希”

6 投票
3 回答
13070 浏览
提问于 2025-04-17 13:56

我在一个Flask项目中使用Flask-Security。基本上,一切都运行得很好,直到我尝试开启密码加密。其实我是按照这个链接的说明来做的:http://packages.python.org/Flask-Security/configuration.html,结果我加了以下内容:

app.config['SECURITY_PASSWORD_HASH'] = 'bcrypt'
app.config['SECURITY_PASSWORD_SALT'] = '$2a$16$PnnIgfMwkOjGX4SkHqSOPO'

但是不幸的是,这导致了一个错误:

File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask_security/decorators.py", line 171, in wrapper
return f(*args, **kwargs)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask_security/views.py", line 72, in login
if form.validate_on_submit():
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask_wtf/form.py", line 123, in validate_on_submit
return self.is_submitted() and self.validate()
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask_security/forms.py", line 165, in validate
if not verify_password(self.password.data, self.user.password):
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/flask_security/utils.py", line 84, in verify_password
return _pwd_context.verify(get_hmac(password), password_hash)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/passlib/context.py", line 2534, in verify
record = self._get_or_identify_record(hash, scheme, category)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/passlib/context.py", line 2258, in _get_or_identify_record
return self._identify_record(hash, category)
File "/home/geoadmin/.virtualenvs/flask/lib/python2.7/site-packages/passlib/context.py", line 1455, in identify_record
raise ValueError("hash could not be identified")
ValueError: hash could not be identified

我对发生了什么感到很困惑。我以为我生成了一个好的bcrypt哈希值,但网站上没有关于密码加密的真实例子,而错误信息让我更加困惑 :/

我使用的软件有: - Ubuntu 12.04LTS - Python 2.7.2 - Flask 0.9 - Flask-Security 1.5.4 - 通过MongoAlchemy在MongoDB 2.2上运行

谢谢你的帮助!!

编辑:感谢Bikeshedder,这可能是问题所在:

# Create a user to test with
@app.before_first_request
def create_user():
    user_datastore.create_user(email='test@test.net', password='testerdetest')

我以为create_user方法会自动加密密码,但显然并不是这样……文档在这方面并不是很清楚:

Class flask_security.datastore.MongoEngineUserDatastore(db, user_model, role_model)
A MongoEngine datastore implementation for Flask-Security that assumes the use of the Flask-MongoEngine extension.
create_user(**kwargs)
Creates and returns a new user from the given parameters.

编辑2:根据Bikeshedder的建议,我把标准用户创建改成了这样:

# Create a user to test with
@app.before_first_request
def create_user():
    user_datastore.create_user(email='test@test.net', password=bcrypt.hashpw('testerdetest', app.config['SECURITY_PASSWORD_SALT'])

这样解决了错误,但却给了我一个“无效密码”的提示,这意味着flask-security在加密时做的和我不一样……真让人烦!

编辑3:我把bcrypt换成了passlib(flask-security也在用这个)

app.config['SECURITY_PASSWORD_SALT'] = '/2aX16zPnnIgfMwkOjGX4S'

而且

user_datastore.create_user(email='test@test.net', password=passlib.hash.bcrypt.encrypt('testerdetest', salt=app.config['SECURITY_PASSWORD_SALT']))

还是得到了无效密码 :( 如果我查看源代码,地址是https://github.com/mattupstate/flask-security/blob/develop/flask_security/utils.py,似乎它只使用了sha512加密……那我就不太明白文档的意思了……

编辑5:问题解决了(谢谢你让我找到了正确的方向!) flask.ext.security.utils.encrypt_password()解决了问题。不过,我还是不确定这到底是不是bcrypt,但至少它是加密过的……

3 个回答

2

这是个老问题,但开发者给出了很清晰的答案...

这完全取决于你是怎么把用户添加到数据库里的。如果你把 SECURITY_REGISTERABLE 设置为 True,并且只是通过内置的注册表单来添加用户,那你就没问题。如果你是通过其他方式添加用户,那么在把用户记录保存到数据库之前,你必须先用 flask_security.utils.encrypt_password 来加密密码。

from flask.ext.security.utils import encrypt_password
db.create_user(email='test@test.com', password=encrypt_password('password'))
10

我也遇到过同样的问题,我是这样解决的:

from flask.ext.security.utils import encrypt_password
user_datastore.create_user(email='test@test.fr', password=encrypt_password('password'))

这样做的好处是,我们可以自己选择 SECURITY_PASSWORD_HASH 和 SECURITY_PASSWORD_SALT 的值。

10

因为你没有说明这个错误是什么时候发生的,所以我只能猜测是在尝试登录的时候出现的。

如果真是这样,那就说明存储在数据库里的密码格式不对。可能这些密码还是明文的,而Flask-Security无法识别使用的加密算法。

解决这个问题最简单的方法就是重置用户的密码。

撰写回答