2015-08-28 136 views
-1

我在SQL中使用PASSWORD来哈希用户密码。构建SQL查询时出现“不支持的操作数类型(%)”

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

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

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

我得到的错误:

unsupported operand type(s) for %: 'TextClause' and 'tuple' 

我在做什么错试图访问加密的密码是什么时候?

+4

您很容易受到SQL注入攻击。分别传递参数,而不是直接将它们格式化为SQL字符串。 – davidism

回答

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) 
) 

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


而不是依赖数据库来散列的口令,使用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') 

在通过这些哈希值,而不是调用SQL PASSWORD

+0

仍然存在登录无法识别加密密码的问题。 PASSWORD(%s)会在将其保存到数据库时对其进行加密,但当我尝试并检索它时不会对其进行解密 – Ricky92d

+0

当您尝试davidism的建议时,是否获得了与%:'TextClause相同的“不受支持的操作数类型'和'元组'错误,还是不同的错误? –

+1

@ Ricky92d你在使用我的答案的第一部分还是第二部分?第二,你根本不应该使用“PASSWORD()”。我已经尝试了两种描述的解决方案,他们都为我工作。 – davidism

相关问题