Flask Python: MySQLdb,%s 无法访问数据库(以防止 SQL 注入)
Flask Python: MySQLdb, %s unable to access database (to prevent SQL injection)
我指的是 post https://ianhowson.com/blog/a-quick-guide-to-using-mysql-in-python/ 更喜欢 %s
,因为它可以防止 SQL 注入,而 '%s'
则不能。但是,我尝试将使用“%s”的工作代码转换为 %s,该代码不再工作。它 return 错误 500,内部服务器错误。
@app.route('/KTM/search', methods=['GET'])
def KTM():
db = MySQLdb.connect(host='xxx.mysql.pythonanywhere-services.com',user='xxx',passwd='xxx',db='jackie$default',cursorclass=MySQLdb.cursors.DictCursor)
curs = db.cursor()
name = request.args['name']
valueMin = request.args['valueMin']
valueMax = request.args['valueMax']
volumeMin = request.args['volumeMin']
volumeMax = request.args['volumeMax']
macd = request.args['macd']
stoch = request.args['stoch']
bollinger = request.args['bollinger']
rsi = request.args['rsi']
atr = request.args['atr']
trade = request.args['trade']
limit = request.args['limit']
offSet = request.args['offSet']
query0 = "SELECT * FROM KTM WHERE Stock LIKE %s%% AND "
query1 = "(Value BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s))) AND "
query2 = "(Volume_changes_pc BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s))) AND "
query3 = "MACD LIKE %s AND "
query4 = "STOCH LIKE %s AND "
query5 = "BOLLINGER LIKE %s AND "
query6 = "RSI LIKE %s AND "
query7 = "ATR LIKE %s AND "
query8 = "TRADE LIKE %s LIMIT %s OFFSET %s"
query = query0+query1+query2+query3+query4+query5+query6+query7+query8
input = name,float(valueMin),float(valueMin),float(valueMax),float(valueMax),float(volumeMin),float(volumeMin),float(volumeMax),float(volumeMax),macd,stoch,bollinger,rsi,atr,trade,int(limit),int(offSet)
try:
curs.execute(query%(input))
g = curs.fetchall()
except Exception:
return 'Error: unable to fetch items'
return jsonify({'Stock': g})
当它是数字时,我确实将输入更改为 float 或 int。
我还检查 MySQL 似乎只使用 SELECT * FROM KTM WHERE Stock LIKE 'G%'
而不是 SELECT * FROM KTM WHERE Stock LIKE G%
。
如何让我的代码 roust 以防止 SQL 注入 %S?我现在使用 Python 3.4
实际上 reading the post you mention 呢?它带有一个非常明确的示例,说明如何使用 db-api
占位符:
cursor.execute("SELECT name, phone_number FROM coworkers WHERE name=%s AND clue > %s LIMIT 5", (name, clue_threshold))
如您所见,变量作为第二个参数传递给 cursor.execute()
,不用于针对 SQL 查询的字符串格式化。
编辑:使用较短的示例可能更容易阅读?
好:
sql = "SELECT name, phone FROM WHERE name=%s AND clue > %s"
args = (name, clue_threshold)
# NO string interpolation
cursor.execute(sql, args)
差:
sql = "SELECT name, phone FROM WHERE name=%s AND clue > %s"
args = (name, clue_threshold)
# BAD string interpolation:
# - does not respect types so may generate invalid SQL
# - also this is plainly a SQL injection vulnerability by itself
# - don't do this!
cursor.execute(sql % args)
你能看出区别吗?
此外,为了便于阅读,您可能希望使用三重引号引起来的字符串:
query = """
SELECT * FROM KTM WHERE
Stock LIKE %s
AND (Value BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s)))
AND (Volume_changes_pc BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s)))
AND MACD LIKE %s
AND STOCH LIKE %s
AND BOLLINGER LIKE %s
AND RSI LIKE %s
AND ATR LIKE %s
AND TRADE LIKE %s
LIMIT %s OFFSET %s
"""
并且 - 对于 like
子句,您必须将通配符添加到您的参数中,即:
sql = "SELECT * FROM workers WHERE name like %s"
arg = "%{name}%".format(name)
cursor.execute(sql, (args,))
最后,您的包罗万象的 except 子句只会阻止您调试代码。你应该 至少 log the exception and traceback.
我指的是 post https://ianhowson.com/blog/a-quick-guide-to-using-mysql-in-python/ 更喜欢 %s
,因为它可以防止 SQL 注入,而 '%s'
则不能。但是,我尝试将使用“%s”的工作代码转换为 %s,该代码不再工作。它 return 错误 500,内部服务器错误。
@app.route('/KTM/search', methods=['GET'])
def KTM():
db = MySQLdb.connect(host='xxx.mysql.pythonanywhere-services.com',user='xxx',passwd='xxx',db='jackie$default',cursorclass=MySQLdb.cursors.DictCursor)
curs = db.cursor()
name = request.args['name']
valueMin = request.args['valueMin']
valueMax = request.args['valueMax']
volumeMin = request.args['volumeMin']
volumeMax = request.args['volumeMax']
macd = request.args['macd']
stoch = request.args['stoch']
bollinger = request.args['bollinger']
rsi = request.args['rsi']
atr = request.args['atr']
trade = request.args['trade']
limit = request.args['limit']
offSet = request.args['offSet']
query0 = "SELECT * FROM KTM WHERE Stock LIKE %s%% AND "
query1 = "(Value BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s))) AND "
query2 = "(Volume_changes_pc BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s))) AND "
query3 = "MACD LIKE %s AND "
query4 = "STOCH LIKE %s AND "
query5 = "BOLLINGER LIKE %s AND "
query6 = "RSI LIKE %s AND "
query7 = "ATR LIKE %s AND "
query8 = "TRADE LIKE %s LIMIT %s OFFSET %s"
query = query0+query1+query2+query3+query4+query5+query6+query7+query8
input = name,float(valueMin),float(valueMin),float(valueMax),float(valueMax),float(volumeMin),float(volumeMin),float(volumeMax),float(volumeMax),macd,stoch,bollinger,rsi,atr,trade,int(limit),int(offSet)
try:
curs.execute(query%(input))
g = curs.fetchall()
except Exception:
return 'Error: unable to fetch items'
return jsonify({'Stock': g})
当它是数字时,我确实将输入更改为 float 或 int。
我还检查 MySQL 似乎只使用 SELECT * FROM KTM WHERE Stock LIKE 'G%'
而不是 SELECT * FROM KTM WHERE Stock LIKE G%
。
如何让我的代码 roust 以防止 SQL 注入 %S?我现在使用 Python 3.4
实际上 reading the post you mention 呢?它带有一个非常明确的示例,说明如何使用 db-api
占位符:
cursor.execute("SELECT name, phone_number FROM coworkers WHERE name=%s AND clue > %s LIMIT 5", (name, clue_threshold))
如您所见,变量作为第二个参数传递给 cursor.execute()
,不用于针对 SQL 查询的字符串格式化。
编辑:使用较短的示例可能更容易阅读?
好:
sql = "SELECT name, phone FROM WHERE name=%s AND clue > %s"
args = (name, clue_threshold)
# NO string interpolation
cursor.execute(sql, args)
差:
sql = "SELECT name, phone FROM WHERE name=%s AND clue > %s"
args = (name, clue_threshold)
# BAD string interpolation:
# - does not respect types so may generate invalid SQL
# - also this is plainly a SQL injection vulnerability by itself
# - don't do this!
cursor.execute(sql % args)
你能看出区别吗?
此外,为了便于阅读,您可能希望使用三重引号引起来的字符串:
query = """
SELECT * FROM KTM WHERE
Stock LIKE %s
AND (Value BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s)))
AND (Volume_changes_pc BETWEEN (IF(%s='_',-5000,%s)) AND (IF(%s='_',5000,%s)))
AND MACD LIKE %s
AND STOCH LIKE %s
AND BOLLINGER LIKE %s
AND RSI LIKE %s
AND ATR LIKE %s
AND TRADE LIKE %s
LIMIT %s OFFSET %s
"""
并且 - 对于 like
子句,您必须将通配符添加到您的参数中,即:
sql = "SELECT * FROM workers WHERE name like %s"
arg = "%{name}%".format(name)
cursor.execute(sql, (args,))
最后,您的包罗万象的 except 子句只会阻止您调试代码。你应该 至少 log the exception and traceback.