У меня есть разные приложения, которые делятся некоторыми данными друг с другом, это делается через контент-провайдера, но когда я загрузил apk, я получил электронное письмо, в котором говорилось: «Ваши приложения используют провайдера контента, который содержит уязвимость SQL-инъекции».
Существует несколько способов исправить это в соответствии с руководством Google:
Если уязвимый ContentProvider должен быть доступен другим приложениям:
Вы можете предотвратить SQL-инъекцию в SQLiteDatabase.query, используя строгий режим с картой проекции.Строгий режим защищает от вредоносных предложений выбора, а проекционная карта защищает от вредоносных предложений проекции.Вы должны использовать обе эти функции, чтобы убедиться, что ваши запросы безопасны.
Вы можете предотвратить внедрение SQL в SQLiteDatabase.update и SQLiteDatabase.delete, используя предложение выбора, которое использует «?»в качестве заменяемого параметра и отдельного массива аргументов выбора.Ваше предложение выбора не должно быть построено из ненадежных входных данных.
Но мне не ясно, как поступить с любым из решений, я не понимаю, как именно использовать карту проекцииили измените код, используя предложение выбора, которое использует «?».Я имею в виду, я видел несколько примеров про ProjectionMap, но какой ключ / значение ему нужен для запроса?Нужно ли писать явные значения, которые я хочу?но что, если это универсальный метод, и я не знаю в этой части кода, что я хочу получить?Или как мне преобразовать любой запрос в ProjectionMap?
Надеюсь, я объясню себе это.
Вот мой код:
@Override
public boolean onCreate() {
gOpenHelper = new GameDBHelper(getContext());
return true;
}
/**
* Builds a UriMatcher that is used to determine witch database request is being made.
*/
public static UriMatcher buildUriMatcher(){
String content = GamesContract.CONTENT_AUTHORITY;
// All paths to the UriMatcher have a corresponding code to return
// when a match is found (the ints above).
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(content, GamesContract.PATH_GAME, GAME);
matcher.addURI(content, GamesContract.PATH_GAME + "/#", GAME_ID);
return matcher;
}
@Override
public String getType(Uri uri) {
switch(sUriMatcher.match(uri))
{
case GAME:
return GameEntry.CONTENT_TYPE;
case GAME_ID:
return GameEntry.CONTENT_ITEM_TYPE;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final SQLiteDatabase db = gOpenHelper.getWritableDatabase();
Cursor retCursor;
switch(sUriMatcher.match(uri))
{
case GAME:
retCursor = db.query(
GameEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
case GAME_ID:
long _id = ContentUris.parseId(uri);
retCursor = db.query(
GameEntry.TABLE_NAME,
projection,
GameEntry._ID + " = ?",
new String[]{String.valueOf(_id)},
null,
null,
sortOrder
);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = gOpenHelper.getWritableDatabase();
long _id;
Uri returnUri;
switch(sUriMatcher.match(uri))
{
case GAME:
_id = db.insert(GameEntry.TABLE_NAME, null, values);
if(_id > 0){
returnUri = GameEntry.BuildGameUri(_id);
} else{
throw new UnsupportedOperationException("Unable to insert rows into: " + uri);
}
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return returnUri;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final SQLiteDatabase db = gOpenHelper.getWritableDatabase();
int rows; // Number of rows effected
switch(sUriMatcher.match(uri))
{
case GAME:
rows = db.delete(GameEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
// Because null could delete all rows:
if(selection == null || rows != 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return rows;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final SQLiteDatabase db = gOpenHelper.getWritableDatabase();
int rows;
switch(sUriMatcher.match(uri))
{
case GAME:
rows = db.update(GameEntry.TABLE_NAME, values, selection, selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if(rows != 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return rows;
}
}