【问题标题】:hashed password never desalts哈希密码从不脱盐
【发布时间】:2012-11-04 21:26:54
【问题描述】:

我正在使用烧瓶微框架并使用 msyql 后端手动设置身份验证。

我的 sql 脚本在 VARCHAR(50)generate_password_hash 函数生成后,以这种数据类型存储散列密码:

  `Password` VARCHAR(50) NOT NULL ,

VARCAHR(50) 我认为已经足够了......

这些是我正在使用的以下库:

from werkzeug import check_password_hash, generate_password_hash


@app.route('/login/', methods=['GET', 'POST'])
def login():
    """Logs the user in."""
    if g.user: return redirect(url_for('main'))
    error = None
    if request.method == 'POST':
        sql = "select password, userid from users where username = " + stringify(request.form['username'])
        cursor = g.db.cursor()
        cursor.execute(sql)
        user = cursor.fetchall()
        user = user[0]
        password = user[0]
        userid = user[1]
        if user is None:
            error = 'Invalid username'
        elif not check_password_hash(password, request.form['password']):
            error = 'Invalid password'
        else:
            flash('You were logged in')
            session['userid'] = userid
            return redirect(url_for('main'))
    return render_template('login.html', error=error)

这就是问题所在:

elif not check_password_hash(password, request.form['password']):

总是返回 false。

更新:我在注册时得到了这个:

Users/Dave/Websites/fh/app.py:143: Warning: Data truncated for column 'Password' at row 1
  g.db.cursor().execute("insert into users (username, email, password) values (%s, %s, %s)" % (username, email, password,))

【问题讨论】:

  • 我想我明白了。我将数据类型设置为 VARCHAR(160),不再截断。
  • 请考虑使用参数化查询而不是使用 "+stringify(...) 进行字符串连接。请参阅docs.python.org/2/library/sqlite3.html(顶部的 4. 绿色框)
  • @sleeplessnerd 它做同样的事情
  • 密码,用户ID = cursor.fetchone()
  • @Dave,只要您使用干净的输入,它就会产生相同的结果。养成使用参数化查询的习惯,否则有一天你会发现自己成为 SQL 注入的受害者。

标签: python mysql passwords flask


【解决方案1】:

设置mysql中的数据类型为Password VARCHAR(160) NOT NULL

【讨论】:

    【解决方案2】:

    你并不需要 160 个字符。

    >>> from werkzeug.security import generate_password_hash
    >>> generate_password_hash("test")
    'sha1$lYmusy7y$8fc97f79a9809ab4eaee4de08d1e182d04f3dc07'
    >>> len(generate_password_hash("test"))
    54
    

    使用默认哈希算法 sha1 就足够了。

    在这里查看它是如何生成的: http://werkzeug.pocoo.org/docs/utils/#werkzeug.security.generate_password_hash

    您使用了尴尬的术语:“脱盐” - 使用这种方法,任何内容都不会以任何方式解密。

    请详细了解这一切是如何运作的,您对用户的安全负责。