为什么Android上的SQLiteQueryBuilder不支持可替换参数?

时间:2016-11-12 14:43:14

标签: android sqlite android-sqlite android-contentprovider

出于安全原因,将值附加到选择字符串是不好的做法。例如:

String selection = TableColumOne + " = " + whereValue;

以及推荐以下内容

    String selection = TableColumOne + " = ?"
    String[] selectionArgs = new String[] { whereValue}

我见过的所有内容提供商示例都使用了SQLiteQueryBuilder,它只是继续前进并完成第一个。这不是坏事吗

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
        String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(NOTES_TABLE_NAME);
    switch (sUriMatcher.match(uri)) {
    case NOTE_ID:
        qb.setProjectionMap(sNotesProjectionMap);
        qb.appendWhere(NoteColumns._ID + "=" +  uri.getPathSegments().get(1));
        break;
        }
        // If no sort order is specified use the default
        String orderBy;
        if (TextUtils.isEmpty(sortOrder)) {
            orderBy = NoteColumns.DEFAULT_SORT_ORDER;
        } else {
            orderBy = sortOrder;
        }

        // Get the database and run the query
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        Cursor c = qb.query(db, projection, selection, selectionArgs, null,     null, orderBy);

        // Tell the cursor what uri to watch, so it knows when its source data     changes
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }

1 个答案:

答案 0 :(得分:0)

欢迎您使用SQLiteQueryBuilder选择参数。在这种情况下,ContentProvider客户端 - 直接或间接地在query()上使用ContentResolver的任何代码 - 很可能在{selection中包含选择参数{1}},包含要在selectionArgs中使用的值。

我假设这句话让你感到不安:

qb.appendWhere(NoteColumns._ID + "=" +  uri.getPathSegments().get(1));

开发人员本可以使用:

qb.appendWhere(NoteColumns._ID + "=?");

然后传入另一个String[]query(),其中包含来电者的selectionArgsuri.getPathSegments().get(1)。这在某种程度上存在风险,因为您实际上并不知道appendWhere()是否真的“追加”该子句,导致其?位于任何调用者提供的?之后。

  

出于安全原因,将值附加到选择字符串是不好的做法

对于网络应用来说,这是一个更大的问题。

在移动世界中,数据通常来自用户。如果用户希望针对用户自己的应用执行a Little Bobby Tables attack,那就是用户的特权。

此代码似乎来自ContentProvider实现。可以导出ContentProvider,也可以不导出ContentProvider。如果导出insert(),以便第三方应用可以使用它,ContentProvider应该进行更多的输入清理。这不一定涉及选择参数,尽管它可以。但是,如果Uri未导出,只要开发人员确信getPathSegments().get(1)永远不会有newtype Ntype a b = N (a -> b) instance Functor (Ntype a) where fmap f (N g) = N (f . g) 的错误值,就没有特别的理由担心使用选择参数。