在 Python 中构建 SQLite 查询但使用 sqlite3 命令行程序执行它?
Build SQLite query in Python but execute it using sqlite3 command line program?
我有一个小型 Python/Flask 网络应用程序,它 return 来自 SQLite table 的 CSV 格式数据。我发现使用 sqlite3
命令行程序将查询结果直接导出到 CSV 文件然后 return CSV 文件比将查询结果读入 Python 更快,将它们写入内存文件,然后 return 内存文件。但是,使用 sqlite3
程序意味着我必须自己构建查询,使我的应用程序受到 SQL 注入攻击。
更快,但容易受到 SQL 注入攻击
queries = """
.mode csv
.headers on
.output /tmp/results.csv
SELECT * FROM mytable WHERE foo = '{0}';
""".format(user_input)
subprocess.check_output(
["sqlite3", "/path/to/mydb.sqlite"], input=bytes(queries.encode("utf-8")))
return send_file("/tmp/results.csv", mimetype="text/csv")
免受 SQL 注入,但速度较慢
conn = sqlalchemy.create_engine("sqlite:////path/to/mydb.sqlite")
result = conn.execute("SELECT * FROM mytable WHERE foo = ?", (user_input,))
csvfile = io.StringIO()
csvwriter = csv.writer(csvfile)
csvwriter.writerow(result.keys())
for row in result.fetchall():
csvwriter.writerow(row)
return Response(csvfile.getvalue(), mimetype="text/csv")
有没有一种方法可以使用 Python 库(sqlalchemy、sqlite3 模块或其他任何东西)来构建一个查询,该查询对 SQL 注入是安全的,但实际上并不执行查询,以便我可以使用 sqlite3
命令行程序通过子进程执行查询?
在 SQL 字符串中,唯一的特殊字符是引号 '
本身。 (以及代码为 0 的字符,这将结束整个查询并导致语法错误。)
要转义单引号,将它们加倍:
user_input.replace("'", "''")
直接 SQLite-to-CSV 导出路径(使用 sqlite3
程序的 .mode csv
)将比更迂回的 SQLite- 具有速度优势to-Python-to-CSV导出路径主要是在selecting大量数据的情况下;当 select 传输少量数据时,速度不会有太大差异。
因此,根据您的模式,一个选择是使用 Python 查询数据库中的一组 ID,然后使用 sqlite3
到 select 其余数据使用 ID。这样,Python 库将清理您的用户输入(防止 SQL 注入等),并且您传递给 sqlite3
程序的内容将不是用户输入,而是您自己查询的 ID。
conn = sqlalchemy.create_engine("sqlite:////path/to/mydb.sqlite")
result = conn.execute("SELECT ID FROM mytable WHERE foo = ?", (user_input,))
ids = [row[0] for row in result.fetchall()]
queries = """
.mode csv
.headers on
.output /tmp/results.csv
SELECT * FROM mytable WHERE ID IN ({0});
""".format(",".join([str(id) for id in ids]))
subprocess.check_output(
["sqlite3", "/path/to/mydb.sqlite"], input=bytes(queries.encode("utf-8")))
return send_file("/tmp/results.csv", mimetype="text/csv")
此方法涉及 2 个查询而不是 1 个,但如果瓶颈是 selecting 所有数据,则差异可能很小。对您的应用进行分析以确定答案。
我有一个小型 Python/Flask 网络应用程序,它 return 来自 SQLite table 的 CSV 格式数据。我发现使用 sqlite3
命令行程序将查询结果直接导出到 CSV 文件然后 return CSV 文件比将查询结果读入 Python 更快,将它们写入内存文件,然后 return 内存文件。但是,使用 sqlite3
程序意味着我必须自己构建查询,使我的应用程序受到 SQL 注入攻击。
更快,但容易受到 SQL 注入攻击
queries = """
.mode csv
.headers on
.output /tmp/results.csv
SELECT * FROM mytable WHERE foo = '{0}';
""".format(user_input)
subprocess.check_output(
["sqlite3", "/path/to/mydb.sqlite"], input=bytes(queries.encode("utf-8")))
return send_file("/tmp/results.csv", mimetype="text/csv")
免受 SQL 注入,但速度较慢
conn = sqlalchemy.create_engine("sqlite:////path/to/mydb.sqlite")
result = conn.execute("SELECT * FROM mytable WHERE foo = ?", (user_input,))
csvfile = io.StringIO()
csvwriter = csv.writer(csvfile)
csvwriter.writerow(result.keys())
for row in result.fetchall():
csvwriter.writerow(row)
return Response(csvfile.getvalue(), mimetype="text/csv")
有没有一种方法可以使用 Python 库(sqlalchemy、sqlite3 模块或其他任何东西)来构建一个查询,该查询对 SQL 注入是安全的,但实际上并不执行查询,以便我可以使用 sqlite3
命令行程序通过子进程执行查询?
在 SQL 字符串中,唯一的特殊字符是引号 '
本身。 (以及代码为 0 的字符,这将结束整个查询并导致语法错误。)
要转义单引号,将它们加倍:
user_input.replace("'", "''")
直接 SQLite-to-CSV 导出路径(使用 sqlite3
程序的 .mode csv
)将比更迂回的 SQLite- 具有速度优势to-Python-to-CSV导出路径主要是在selecting大量数据的情况下;当 select 传输少量数据时,速度不会有太大差异。
因此,根据您的模式,一个选择是使用 Python 查询数据库中的一组 ID,然后使用 sqlite3
到 select 其余数据使用 ID。这样,Python 库将清理您的用户输入(防止 SQL 注入等),并且您传递给 sqlite3
程序的内容将不是用户输入,而是您自己查询的 ID。
conn = sqlalchemy.create_engine("sqlite:////path/to/mydb.sqlite")
result = conn.execute("SELECT ID FROM mytable WHERE foo = ?", (user_input,))
ids = [row[0] for row in result.fetchall()]
queries = """
.mode csv
.headers on
.output /tmp/results.csv
SELECT * FROM mytable WHERE ID IN ({0});
""".format(",".join([str(id) for id in ids]))
subprocess.check_output(
["sqlite3", "/path/to/mydb.sqlite"], input=bytes(queries.encode("utf-8")))
return send_file("/tmp/results.csv", mimetype="text/csv")
此方法涉及 2 个查询而不是 1 个,但如果瓶颈是 selecting 所有数据,则差异可能很小。对您的应用进行分析以确定答案。