在Android中使用预准备语句查询?

sha*_*ter 14 sql sqlite android prepared-statement

在Android中,android.database.sqlite.SQLiteStatement允许我在SQLite中使用预准备语句来避免注入攻击.它的execute方法适用于创建/更新/删除操作,但似乎没有任何返回游标等的查询方法.

现在在iOS中我可以创建类型的预准备语句sqlite3_stmt*并将它们用于查询,所以我知道这不是SQLite的限制.如何在Android中使用预准备语句执行查询?

zap*_*apl 40

准备好的声明允许您做两件事

  • 加速性能,因为数据库不需要每次都解析语句
  • 在语句中绑定和转义参数,以防止注入攻击

sqlite3_prepare不确切知道Androids SQLite实现在何处/何时实际使用(afiak not sqlite3_prepare_v2- 请参见此处)但它确实使用它,否则您无法获得已编译的sql语句缓存错误的Reached MAX大小.

因此,如果您想查询数据库,您必须依赖于实现,我无法知道如何使用它SQLiteStatement.

关于注入安全性,每个数据库查询,插入等方法都有(有时是替代)版本,允许您绑定参数.

例如,如果你想获得一个Cursor出来的

SELECT * FROM table WHERE column1='value1' OR column2='value2'
Run Code Online (Sandbox Code Playgroud)

Cursor SQLiteDatabase#rawQuery(

  • String sql,:完整的SELECT陈述,可以包括?无处不在
  • String[] selectionArgs:替换的值列表?,按顺序显示

)

Cursor c1 = db.rawQuery(
    "SELECT * FROM table WHERE column1=? OR column2=?",
    new String[] {"value1", "value2"}
);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

通过ContentProviders - 这种情况略有不同,因为您与抽象提供者而不是数据库进行交互.实际上并不能保证有一个sqlite数据库支持ContentProvider.因此,除非您知道哪些列/提供者如何在内部工作,否则您应该坚持文档所说的内容.

Cursor ContentResolver#query(

  • Uri uri,:表示数据源的URI(内部转换为表)
  • String[] projection,:所需列的列表,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);
Run Code Online (Sandbox Code Playgroud)

提示:如果你想在LIMIT这里,你可以将它添加到ORDER BY子句中:

String sortOrder = "somecolumn LIMIT 5";
Run Code Online (Sandbox Code Playgroud)

或者根据实现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");
Run Code Online (Sandbox Code Playgroud)

在所有情况下,?将替换为您在bind参数中放置的转义版本.

?+ "hack'me"='hack''me'