AlarmManager и WakefullBroadcastReceiver насколько приватны передаваемые дополнения?

Я пытаюсь реализовать планирование сигналов тревоги с помощью AlarmManager. Поскольку при срабатывании будильника я хочу использовать WakefulBroadcastReceiver, который запускает IntentService для выполнения некоторой фоновой работы.

У меня есть несколько вопросов, связанных с безопасностью/конфиденциальностью параметров, передаваемых для целей тревоги.

  1. При установке PendingIntent для будильника я делаю что-то вроде:

    Intent myIntent = new Intent(context, MyReceiver.class);        
    myIntent.putExtra("test", "testValue");
    Bundle bundle = new Bundle();
    bundle.putParcelable("bundleValue", bundleTestValue2);
    myIntent.putExtra("test3", bundle);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
        myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    

Мой вопрос: насколько приватны значения, установленные как Extra для pendingIntent будильника? Есть ли шанс, что они будут прочитаны каким-либо другим приложением, поскольку оно используется менеджером Android Alarm после того, как оно запланировано?

  1. Имея такой приемник

    public class MyReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
           startWakefulService(context, MyIntentService);
    }
    

И в манифесте андроида

 <receiver
            android:name=".receivers.MyReceiver"
            android:exported="false"/>

 <service 
          android:name=".MyIntentService" 
          android:exported="false"/>

И сервис

public class MyIntentService extends IntentService {

  @Override
  protected void onHandleIntent(Intent intent) {

     try {
          //logic here
     } catch{
     } finaly{
          MyReceiver.completeWakefulIntent(intent);
     } 
}

Позвонить из моей активности

sendBroadcast(new Intent(context, MyReceiver.class).putExtra(...);

Запланировать отложенное намерение из будильника

Intent myIntent = new Intent(context, MyReceiver.class);        
myIntent.putExtra("test", "testValue");

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
    myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

насколько этот ресивер открыт для других приложений? Может ли он реагировать на другие приложения, кроме моего? Возникает ли при этом какие-либо возможные проблемы с безопасностью?

Спасибо.

Позднее редактирование: поскольку WakefullBroadcastReceiver кажется единственным способом, гарантирующим, что моя служба получит частичную блокировку пробуждения, как я могу на 100% убедиться, что никакие другие приложения не будут знать о моем приемнике и что мой приемник не получит никаких других вызовов, кроме сделанные из моей деятельности или из моего набора Alarm?

Как будет работать шаблон WakefullBroadcastReceiver по сравнению с WakefulIntentService CommonsWare?

Позднее редактирование. Наконец-то мне удалось завершить реализацию.

  1. Как указывалось ранее, мои WakefulBroadcastReceiver и IntentService объявлены как exported="false" в моем манифесте Android, что, насколько я понимаю, означает, что только мое приложение может получить к ним доступ. Поскольку ресивер не экспортируется, принимает ли он трансляции из-за пределов приложения?

  2. При установке будильника я использую этот PendingIntent:

    Intent myIntent = new Intent(context, MyReceiver.class);
    myIntent.putExtra("databaseId", "1"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

  3. При звонке из моей деятельности я делаю:

sendBroadcast(new Intent(context, MyReceiver.class).putExtra("databaseId", "1"));

Этого достаточно?


person Alin    schedule 27.01.2017    source источник
comment
И WakefulBroadcastReceiver, и WakefulIntentService используют комбинацию BroadcastReceiver и IntentService. Что касается ваших опасений, то они идентичны.   -  person CommonsWare    schedule 31.01.2017
comment
@CommonsWare большое спасибо за ваше время. Что касается безопасности WakefullBroadcastReceiver, можете ли вы мне что-нибудь сказать? Как я могу убедиться, что его intent не читаются другими приложениями или другие приложения не взаимодействуют с ним, отправляя ему широковещательные сообщения?   -  person Alin    schedule 31.01.2017
comment
У вас уже есть развернутый ответ на эту тему. Начальная фраза Василия хороша: В общем, я бы сказал, что помещать конфиденциальные данные в Intent небезопасно. Более того, вам не нужно помещать конфиденциальные данные в Intent, где Intent перенаправляет обратно в ваше собственное приложение. Используйте некоторый идентификатор, который не имеет смысла для посторонних, но указывает, как загружать данные (например, первичный ключ к таблице базы данных).   -  person CommonsWare    schedule 31.01.2017
comment
@CommonsWare действительно, это то, что я делаю прямо сейчас, используя первичные ключи в таблицах в качестве дополнений. Однако меня все еще беспокоит, могут ли другие приложения транслировать на мой приемник или нет... Или когда я использую в своей деятельности sendBroadcast, идет ли моя трансляция в другие приложения или нет...   -  person Alin    schedule 31.01.2017
comment
Однако меня все еще беспокоит, могут ли другие приложения транслировать на мой приемник или нет — каждый раз, когда вы используете PendingIntent, вам не нужно экспортировать этот компонент, поэтому сторонние приложения не должны иметь доступ к вашему приемнику. Каждый раз, когда вы работаете с одним из ваших собственных компонентов (например, вызываете startService() из получателя), вам не нужно экспортировать компонент. Таким образом, у вас не должно быть проблем здесь. Если вы вызываете sendBroadcast() с явным Intent, широковещательная рассылка идет только к этому получателю; с неявным Intent трансляция идет всем зарегистрированным слушателям.   -  person CommonsWare    schedule 31.01.2017
comment
@CommonsWare Последняя фраза without an implicit Intent, the broadcast goes to all registered listenters? Я добавил некоторый код, и WakefullBroadcastReceiver, и IntentService являются exported=false. Я также добавил, как я либо готовлю PendingIntent из Alarm, либо вызываю sendBroadcast из Activity приложения. Насколько я понимаю, sendBroadcast, заявив о намерении, идет только к моему получателю, а не к другим. Также будильник с PendingIntent также поступает на мой приемник. Наличие exported=false делает приемник недоступным для других приложений. Правильный?   -  person Alin    schedule 31.01.2017
comment
sendBroadcast объявил о намерении - мне неясно, что это значит. Явное Intent похоже на new Intent(this, YourReceiver.class). Это пойдет только к YourReceiver. Неявное Intent похоже на new Intent("your.custom.action.STRING"). Это касается любого, кто хочет слушать такие передачи. В вашем случае не используйте <intent-filter> на <receiver> и используйте явный Intent для вашей трансляции. Или не используйте sendBroadcast(), а вместо этого вызовите IntentService напрямую в случаях, когда он не срабатывает при тревоге.   -  person CommonsWare    schedule 31.01.2017
comment
@CommonsWare Я хочу использовать приемник, чтобы мне не нужно было удерживать wakelock в службе (об этом позаботится WakefullBroadcastReceiver), поэтому я использую sendBroadcast within my app. Я пропустил явное/неявное, являющееся разными словами, не то, чтобы я внимательно перечитал, я понимаю. Я отправляю широковещательную рассылку типа sendBroadcast(new Intent(context, MyReceiver.class).putExtra(...), чтобы трансляция шла только на мой приемник, а не на другие.   -  person Alin    schedule 31.01.2017
comment
@CommonsWare извините, что отнял у вас время, я добавил более позднее редактирование, пожалуйста, проверьте, правильно ли я понял. Поскольку я использую sendBroadcast с явным Intent, трансляция должна идти только на мой приемник. То же самое касается PendingIntent в случае тревоги. Если они не экспортируются, их нельзя вызывать или прослушивать вне процесса моего приложения, не оставляя угроз безопасности. В качестве предостережения я передаю только некоторые идентификаторы PK из базы данных как Extras. Я правильно понял?   -  person Alin    schedule 16.02.2017
comment
Зачем вы отправляете трансляцию самому себе? Используйте шину событий и держите все в процессе, чтобы ускорить обработку и избежать риска для безопасности. То, что вы предлагаете, подходит для вашего сценария PendingIntent.   -  person CommonsWare    schedule 16.02.2017
comment
@CommonsWare И PendingIntent, и вызов из Activity вызывают один и тот же IntentService, что означает, что он делает одно и то же, только параметры могут быть разными. Я использовал sendBroadcast в своей деятельности, чтобы воспользоваться преимуществами wakelock, которые WakefulBroadcastReceiver обрабатывает сам по себе. Таким образом, приложение, вызываемое либо из Alarm, либо из самого себя, запускает BroadcastReceiver, который получает wakelock во время выполнения IntentService. Например, вызов из действия может занять несколько минут, поэтому мне нужно иметь частичную блокировку пробуждения во время работы IntentService...   -  person Alin    schedule 16.02.2017
comment
Я решил просто позвонить в Службу из сигнализации. Я протестировал его, и, кажется, он работает... Я знаю, что нет никакой гарантии, что служба получит шанс восстановить блокировку, но, похоже, это происходит при моем небольшом количестве тестов. Я проведу тестирование на других устройствах.   -  person Alin    schedule 17.02.2017


Ответы (1)


Соображения о конфиденциальности, связанные с Intent дополнительными функциями

В общем, я бы сказал, что хранить конфиденциальные данные в Intent небезопасно.

Теоретически, если Intent может использоваться только конкретным приложением (обсуждается позже), то только это приложение должно иметь возможность видеть его содержимое. Однако, учитывая огромное количество устройств Android и версий ОС (включая рутированные устройства и пользовательские ПЗУ), я бы не стал на это рассчитывать.

Вы не указали тип конфиденциальных данных, которые хотели бы передать в Intent дополнениях, поэтому я могу дать только общие рекомендации:

  1. Убедитесь, что вы понимаете «уровень конфиденциальности» рассматриваемых данных: это секрет или только ограниченный доступ? Или, может быть, он публичный (в этом случае защита не нужна)?
  2. Попробуйте найти другой подход, не связанный с передачей конфиденциальных данных в Intent (сам я с такой необходимостью не сталкивался).
  3. Если вам абсолютно необходимо передавать конфиденциальные данные в Intent дополнительные функции, подумайте о их шифровании. Модель шифрования должна быть адекватной «уровню конфиденциальности» данных и потенциальному вреду, который может быть нанесен в случае перехвата этих данных (он может доходить до шифрования «на стороне сервера»).

Вопросы конфиденциальности/безопасности, связанные с BroadcastReceiver

В общем, BroadcastReceiver — это компонент, который принимает «общесистемные» широковещательные сообщения. Тот факт, что трансляции являются «общесистемными», сам по себе должен говорить об уровне конфиденциальности, связанном с ними.

При этом есть один механизм, с помощью которого разработчики могут ограничивать области широковещания: настраиваемые разрешения. Использование настраиваемых разрешений позволяет использовать два «уровня контроля» над трансляциями:

  1. Если для трансляции требуется специальное разрешение, то только если BroadcastReceiver имеет это разрешение, она получит трансляцию.
  2. Если BroadcastReceiver фильтрует входящие передачи по определенным разрешениям, то на этот приемник будут доставлены только передачи, имеющие это разрешение.

Хотя на первый взгляд вышеуказанные пункты могут показаться похожими, это разные схемы, которые можно использовать по отдельности или комбинировать. Первая схема связывает широковещательную рассылку с разрешением (и отправитель этой трансляции не обязательно имеет это разрешение сам), в то время как вторая схема фильтрует все широковещательные передачи по определенному разрешению (и получатель должен иметь это разрешение).

Лучший подход в вашем случае

EDIT: это МОЖЕТ БЫТЬ лучшим подходом, если «бодрствование» не будет частью требований. Но это. Поскольку нет гарантии, что Service, запущенный AlarmManager, получит возможность получить блокировку пробуждения - этот подход не подходит для случая OP.

Обратите внимание, что широковещательные рассылки и настраиваемые разрешения были разработаны для того, чтобы ввести «развязку» на уровне приложений — эта схема позволяет приложению-отправителю быть полностью независимым от принимающего приложения, пока они соглашаются на одно настраиваемое разрешение (ну, та же схема также используется для предустановленных общедоступных разрешений, но вы не хотели бы защищать свои конфиденциальные данные с помощью общедоступного разрешения).

Однако в вашем случае отправитель и получатель являются одним и тем же приложением. В такой настройке вам действительно не нужны все проблемы, связанные с трансляциями — просто создайте PendingIntent, который запускает требуемый Service внутри вашего приложения, и вы получите все это сразу:

  • PendingIntent и связанный с ним Intent запускают определенный Service в вашем приложении (по имени), поэтому никакое другое приложение не может его перехватить (теоретически, помните приведенное выше обсуждение).
  • Цель Service может быть неэкспортируемой, поэтому никакое другое приложение не может получить к ней доступ каким-либо образом.

Пожалуйста :)

person Vasiliy    schedule 28.01.2017
comment
Ну @Василий просто вау. Такой неожиданный и подробный ответ. Я знал о широкой доступности трансляций этой системы, поэтому и задал вопрос. В моем приложении, где у меня есть служба, которая должна общаться с действием, я использовал LocalBroadcastReceiver, учитывая, что это не вызывает проблем с безопасностью. Что касается намерений, вместо передачи личных данных я переключился на передачу идентификатора базы данных и получение строки при пробуждении приложения. Я использовал WakefulBroadcastReceiver, потому что это казалось удобным способом сохранить блокировку. Мне нужно обработать пробуждение в моем IntentService без него, верно? - person Alin; 31.01.2017
comment
@ Алин, извини - меня увлекла часть вопроса о безопасности / конфиденциальности, и я пропустил требование бодрствования. К сожалению, насколько мне известно, нет никакой гарантии, что Service, запущенный AlarmManager, сможет получить блокировку пробуждения до того, как устройство перейдет в спящий режим. Поэтому, если требуется бодрствование, вам придется использовать BroadcastReceiver. Я отредактирую ответ, чтобы не вводить других людей в заблуждение. - person Vasiliy; 31.01.2017
comment
Хорошо, если я сделаю это так, как в моем другом вопросе: > stackoverflow.com/questions/41953458/ Я думаю, что служба получит возможность получить пробуждение... потому что это первое, что она делает... И поскольку мне нужно, чтобы служба вызывалась из либо активность, либо будильник, мне нужен механизм для удержания пробуждения в самой службе. Имеет смысл? - person Alin; 31.01.2017
comment
@ Алин, я отвечу на другой вопрос. - person Vasiliy; 31.01.2017
comment
похоже, что я могу застрять с WakefullBroadcastReceiver... Добавив к нему `exported=false', предотвратить его вызов из внешних источников? Добавит ли это дополнительную безопасность? - person Alin; 31.01.2017
comment
@ Алин, я не знал, что BroadcastReceiver можно не экспортировать... Спасибо. Кажется, это хорошо подходит для вашего случая. - person Vasiliy; 31.01.2017