在Android中,android.database.sqlite.SQLiteStatement
允许我在SQLite中使用预准备语句来避免注入攻击。它的execute
方法适用于创建/更新/删除操作,但似乎没有任何方法可用于返回游标等的查询。
现在在iOS中我可以创建类型为sqlite3_stmt*
的预准备语句并将它们用于查询,所以我知道这不是SQLite的限制。如何在Android中使用预准备语句执行查询?
答案 0 :(得分:40)
准备好的声明允许你做两件事
我不确切知道Androids SQLite实现在何处/何时实际使用sqlite3_prepare
(afiak not sqlite3_prepare_v2
- 请参阅here)但它确实使用了它,否则你无法获得SQLiteStatement
3}}
因此,如果您想查询数据库,您必须依赖于实现,我无法通过Cursor
进行查询。
关于注入安全性,每个数据库查询,插入等方法都有(有时是替代)版本,允许您绑定参数。
E.g。如果你想从
中获得SELECT * FROM table WHERE column1='value1' OR column2='value2'
Cursor SQLiteDatabase#rawQuery(
String sql
SELECT
,:完整的?
声明,其中包含String[] selectionArgs
无处不在?
:替换Cursor c1 = db.rawQuery(
"SELECT * FROM table WHERE column1=? OR column2=?",
new String[] {"value1", "value2"}
);
的值列表,按其显示)
Cursor SQLiteDatabase#query (
String table
JOIN
,:表名,可以包含String[] columns
等null
,:所需列的列表,*
= String selection
WHERE
,WHERE
子句无?
可以/应该包含String[] selectionArgs
?
,:替换String groupBy
的值列表,按其显示GROUP BY
,GROUP BY
条款没有String having
HAVING
,HAVING
条款没有String orderBy
ORDER BY
:ORDER BY
条款没有)
Cursor c2 = db.query("table", null,
"column1=? OR column2=?",
new String[] {"value1", "value2"},
null, null, null);
ContentProvider
通过ContentProviders - 由于您与抽象提供者而不是数据库进行交互,因此情况略有不同。实际上并不能保证有一个sqlite数据库支持Cursor ContentResolver#query(
。因此,除非您知道哪些列/提供者如何在内部工作,否则您应该坚持文档所说的内容。
Uri uri
String[] projection
,:表示数据源的URI(内部转换为表格)null
,:所需列的列表,*
= String selection
WHERE
,WHERE
子句无?
可以/应该包含String[] selectionArgs
?
,:替换String sortOrder
的值列表,按其显示ORDER BY
:ORDER BY
条款没有)
Cursor c3 = getContentResolver().query(
Uri.parse("content://provider/table"), null,
"column=? OR column2=?",
new String[] {"value1", "value2"},
null);
LIMIT
提示:如果您想ORDER BY
在这里,可以将其添加到String sortOrder = "somecolumn LIMIT 5";
子句中:
ContentProvider
或取决于Uri
的实施,将其作为参数添加到Uri.parse("content://provider/table?limit=5");
// or better via buildUpon()
Uri audio = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
audio.buildUpon().appendQueryParameter("limit", "5");
:
?
在所有情况下,?
都将替换为您在bind参数中放置的转义版本。
"hack'me"
+ 'hack''me'
= {{1}}