TypeError:hash必须是unicode或bytes,而不是None

时间:2016-09-04 12:23:19

标签: python unicode hash flask typeerror

我正在使用mongoengine开展Flask项目工作。用户注册时,使用 passlib.hash 注册密码到密码。当我尝试在登录验证中读取密码时,我遇到了这个错误。

TypeError:hash必须是unicode或bytes,而不是None

enter image description here

回溯:

TypeError
TypeError: hash must be unicode or bytes, not appname.models.User

Traceback (most recent call last)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)

File "/*/**/***/***/appname/views.py", line 207, in login
if sha256_crypt.verify(u''+ passW,user):

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/passlib/utils/handlers.py", line 567, in verify
self = cls.from_string(hash, **context)

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/passlib/handlers/sha2_crypt.py", line 285, in from_string
hash = to_unicode(hash, "ascii", "hash")

File "/*/**/***/***/appname/env/lib/python2.7/site-packages/passlib/utils/__init__.py", line 617, in to_unicode
raise ExpectedStringError(source, param)

TypeError: hash must be unicode or bytes, not appname.models.User
The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.

To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.

You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:

dump() shows all variables in the frame
dump(obj) dumps all that's known about the object

以下是我的 views.py 代码:

@app.route("/login", methods=['GET','POST'])
def login():
    if current_user.is_authenticated:
        flash("You're already registered", "info")
        return redirect(url_for('profile')+('/'+current_user.slug))

    form = LoginForm()
    passW = form.password.data

    if request.method == 'POST':
        form = LoginForm()

        if form.validate_on_submit():
            user = User.objects(email=form.email.data, password=str(passW)).first()
            if sha256_crypt.verify(passW, user):
                login_user(user, form.remember_me.data)
                slug = slugify(user.name)

                flash('We are glad you came {}.'.format(user.name),'success')
                return redirect(request.args.get('next') or url_for('profile', slug=slug))

            else:
                flash('Wrong username or password.','danger')
                return render_template("login.html", form=form, title="Cp-Login")
    return render_template("login.html", form=form, title="Cp-Login")

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

我想问题出在这里:

user = User.objects(email=form.email.data, password=str(passW)).first()

如果您的数据库找不到任何匹配用户,则用户将为none。所以你最好使用if else来判断用户是否先存在。

修改

来自Passlib的文档,

>>> # import the hash algorithm
>>> from passlib.hash import sha256_crypt

>>> # generate new salt, and hash a password
>>> hash = sha256_crypt.encrypt("toomanysecrets")
>>> hash
'$5$rounds=80000$zvpXD3gCkrt7tw.1$QqeTSolNHEfgryc5oMgiq1o8qCEAcmye3FoMSuvgToC'

>>> # verifying the password
>>> sha256_crypt.verify("toomanysecrets", hash)
True
>>> sha256_crypt.verify("joshua", hash)
False

您的代码

if sha256_crypt.verify(passW, user):

应该是

if sha256_crypt.verify(passW, user.password):

如果您存储用户密码,请使用Passlib。但通常你应该使用django内置authenticating来做这样的事情。

答案 1 :(得分:0)

就像@aison上面所说的那样,我必须使用objects字段变量将对象变量更改为user.password

if sha256_crypt.verify(passW, user.password): 

还需要更改模型查询集本身。我删除了查询中的密码字段,因为在上面的表单验证之后已经验证了sha256_crypt语句的密码

修改前

user = User.objects(email=form.email.data, password=str(passW)).first()
修改后

user = User.objects(email=form.email.data).first()

哈希验证声明,@ aison建议完成剩下的工作

if sha256_crypt.verify(passW, user.password):