构建SQL查询时"%支持的操作数类型不受支持"

Ric*_*92d -1 python mysql flask

PASSWORD在SQL中使用哈希用户密码.

sql = text('insert into account values("%s", "%s", "%s", PASSWORD("%s"), "1" )'%(fname, lname, user_name, password))
Run Code Online (Sandbox Code Playgroud)

当我尝试使用密码登录时,它不允许我访问该帐户.

sql = text('select * from account where account.user_name = "%s"  and account.password = PASSWORD("%s") and account.active = ' + '"' + '1' + '"')%(user_name, password)
Run Code Online (Sandbox Code Playgroud)

我收到错误:

 unsupported operand type(s) for %: 'TextClause' and 'tuple'
Run Code Online (Sandbox Code Playgroud)

尝试访问加密密码时,我做错了什么?

dav*_*ism 11

即时错误是在第一实施例时使用的字符串格式化%的字符串,然后包围的结果text,而第二个尝试使用串格式化text对象.

更严重的问题是,你已经通过直接格式化用户输入的SQL字符串,而不是单独将它们打开自己注入攻击.

看起来您正在使用Flask-SQLAlchemy.在这种情况下,编写参数化查询并传递要正确转义的参数execute.

db.engine.execute(
    'insert into account values(?, ?, ?, PASSWORD(?), ?)',
    (fname, lname, user_name, password, True)
)

db.engine.execute(
    'select * from account where account.user_name = ?  and account.password = PASSWORD(?) and account.active = ?,
    (user_name, password, True)
)
Run Code Online (Sandbox Code Playgroud)

参数化概念与任何其他数据库驱动程序类似.


而不是依靠数据库来散列密码,使用passlib库是一个更强大的替代方案.它包含了更强大的哈希值,以及为"弃用"散列和升级存储价值的能力.

from passlib.hash import pbkdf2_sha512

# when creating a user, generate the hash with passlib
# and don't use PASSWORD() in SQL
password = pbkdf2_sha512.encrypt('secret')

# example login
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        r = engine.execute('select * from account where account.name = ? and account.active = ?', (username, True))

        if r:
            user = r[0]

            # verify the hash using passlib, not SQL
            if pbkdf2_sha512.verify(password, user.password):
                # active user, correct password, do the login
                return 'good credentials'

        # incorrect username or password
        return 'bad credentials'

    return render_template('login.html')
Run Code Online (Sandbox Code Playgroud)

传递这些哈希值,而不是PASSWORD在SQL中调用.