2013-03-20 7 views
5

Ich arbeite in einer Firma, die mehrere Apps produziert, nicht alle diese Anwendungen haben die gleiche Signatur oder mehr wie wir haben mindestens 5-6 Apps Zertifikate vorläufig. Wir haben versucht, einen Mechanismus zu erstellen, bei dem alle Apps des Unternehmens auf dem gleichen Gerät den gleichen Namen haben. Wenn der Benutzer beispielsweise vom Markt App A installiert hat und keine App installiert ist, wird jetzt eine neue ID generiert Er installiert App A, App B sollte die gleiche ID wie App A haben (ID ist nur ein generierter UUID-Typ Nr. 4) usw.Android: validieren Sie die Identität des Absenders Absicht

Wir verwenden derzeit Broadcast und nur Apps mit unserer Erlaubnis können das empfangen Senden und senden Sie die ID mit einer anderen Übertragung (diesmal explizit). Die Übertragung und die Antworten sind mit unserer Erlaubnis mit Signaturstufe geschützt, das ist natürlich nicht hilfreich, da wir mehr als eine Signatur haben.

Ich habe versucht, eine Absicht Broadcast zu schreiben und zu erholen, die eigenen Schutzmechanismus haben kann, der nicht auf nur eine Signatur begrenzt ist, aber mehrere, das Problem ist, dass Dinge wie Binder.getSenderUID() für Broadcasts nicht funktioniert und ich bekomme meine eigene UID. es sieht so aus, als hätte ich keine Möglichkeit, die Identität meines Snders zu bekommen, es sei denn, er selbst schreibt seine ID in die Absicht, was NICHT etwas ist, dem ich vertrauen kann, da es leicht gefälscht werden kann. Die Verwendung von Verschlüsselung erfordert, dass die Apps mit einem Schlüssel auf sie kommen, der nicht noch einmal gesichert ist. Die Überprüfung auf einen Server dauert zu lange und auf dem Handy ist kein Erfolg garantiert, da nicht 100% sicher sind.

Jeder hat eine Idee, wie man eine validate \ sichere Nachricht von einer App zur anderen bekommen kann (alle meine Apps können aber unterschiedliche Signaturen haben).

Antwort

2

Sorry für späte Antwort ...

Bind braucht Zeit, und was noch wichtiger ist, seine asynchron. Es gibt jedoch eine Möglichkeit, eine synchrone Bindung zu erstellen - vorausgesetzt, der Dienst, den Sie zu kontaktieren versuchen, ist zu diesem Zeitpunkt bereits gestartet. Android erlaubt dies mehr für BroadcastReceivers (die async in der Natur sind und daher nicht normal BindService verwenden) ein BroadcastReceiver hat eine "PeekService" -Methode.

Wenn Sie wollen, es zu benutzen, ohne eine Sendung zu hören, können Sie, indem Sie:

final IBinder[] b = new IBinder[1]; 
new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 
     b[0] = peekService(context, intent); 
    } 
}.onReceiver(context, intent); 

IMyInterface i = IMyInterface.Stub.asInterface(b[0); 

Notiz, die Sie den Dienst nicht binden, so stellen Sie sicher, dass bei auf jedem Gebrauch spähen.

+0

dies ist ein Hack, bnut das ist verdammt gut, ich nehme auch der Service vor Ort sein muss, aber soweit ich weiß, BR sollten Nachrichten aus dem Dienst bekommen und senden Sie es zurück oder senden Sie es zu einer Aktivität mit einer Absicht, es ist nicht dazu bestimmt, an einen Service zu binden ... so bricht diese Methode wirklich die Idee eines BR ... – codeScriber

4

Wie immer mit einer herausfordernden Frage hier bekomme ich nie eine richtige, wenn überhaupt! ' antworte, also bin ich gezwungen, es selbst zu finden.

Das Problem mit Intents ist, dass es nicht möglich ist, den Absender als die Parallele zu Multicast in einem Netzwerk zu erhalten, wo die Adresse des Absenders nicht wichtig ist.

Wenn ich die UID des Snders bekommen möchte, muss ich einen "remote" Prozess machen, auch wenn er lokal ist, anstatt Broadcast IPC zu verwenden, muss ich AIDL mit IBInder Implementierung verwenden. Sobald ich ein Binder-Objekt habe, kann ich meinen Dienst getCallingUid() aufrufen und die UID des Aufrufers abrufen, dies ermöglicht es mir, PackageManager zu fragen, mir sein öffentliches Zertifikat zu geben (ohne den Prozess selbst zu fragen, frage ich das OS) Vergleichen Sie es mit einer Reihe von Zertifikaten, die ich im Vorfeld in der apk vorbereitet habe.

Die aufrufende Anwendung auf der anderen Seite (der andere Prozess, der mir ihre ID sendet) muss nur die BindService (Service, Conn, Flags) -Methode verwenden, um an mich zu binden. Der Nachteil dieses Ansatzes ist natürlich der zeitaufwändige Prozess, Bind braucht Zeit, es ist ein Async-Aufruf, der den Kernel durchläuft und nicht so schnell ist wie die Bindung an einen lokalen Dienst. Außerdem, da ich vielleicht mehrere Anwendungen habe, muss ich den Zugriff auf meine interne ID synchronisieren, sodass nur der erste verbindliche Anruf, der nicht fehlgeschlagen ist, für mich festgelegt und ID wird. Ich muss noch überprüfen, ob ich die Messenger-Methode verwenden kann, die die Multithread-Probleme verhindert.

Hofft, dass dies jemand anderen hilft.

0

Wie bereits erwähnt, ist die Bindung wahrscheinlich die beste Lösung. Sie könnten jedoch erwägen, zu einer Aktivität anstelle eines BroadcastReceivers zu wechseln, dann können Sie getCallingActivity() verwenden, vorausgesetzt, Sie starteten mit startActivityForResult().

Erklären Sie Aktivität wie folgt es „stille“ wie ein BroadcastReceiver zu machen:

<activity 
    android:name=".FauxReceiver" 
    android:theme="@android:style/Theme.NoDisplay" 
    android:excludeFromRecents="true" 
    android:noHistory="true" 
> 
    <intent-filter> 
     ... 
    </intent-filter> 
</activity> 

Inspiration: How to get the sender of an Intent?

+1

Wir arbeiten an einer Bibliothek für die Überprüfung der Sender und Empfänger von 'Intent's, die diese Technik verwenden, um damit zu beginnen, da es die einfachste ist. Mehr erfahren Sie hier https://dev.guardianproject.info/projects/trustedintents/wiki –

+0

@ Hans-ChristophSteiner Sieht gut aus. Es ist merkwürdig, dass sie den Absender nicht in alle Intent-Aufrufe eingeschlossen haben (nicht nur diejenigen, die ein Ergebnis erfordern), da die Kosten vermutlich minimal gewesen wären. –

-1

ich nach einem Weg suchen, den Paketnamen der Anwendung, um zu überprüfen, dass die gesendeten Absicht, die ich von meinem Absichtsfilter erhalten habe. Diese Aktivität in meiner App, die den Intent-Filter behandelt, erfordert, dass der Absender des Absenders ihre Prozess-ID in ein Feld "Intent-Extras" einfügt. Meine empfangende Aktivität kann dann den zugehörigen Anwendungspaketnamen vom ActivityManager abrufen.

Hier ist ein Beispielcode, den ich beim Verschieben durch StackOverflow gefunden habe.

Konstanten für beide Apps

benötigt
public static final String EXTRA_APP_ID; 
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY"; 

Aktivität aufrufen

Intent verifyIntent = new Intent(); 
    verifyIntent.setAction(Consts.ACTION_VERIFY); 
    verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid()); 
    // Verify that the intent will resolve to an activity 
    if (verifyIntent.resolveActivity(getPackageManager()) != null) { 
    startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY); 
    } else { 
     Log.d(TAG, "Application not found."); 
    } 

App empfangen

Manifest

 <activity 
      android:name="com.example.receivingapp.ReceivingActivity" 
      android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="com.example.receivingapp.VERIFY" /> 
       <category android:name="android.intent.category.DEFAULT" /> 
      </intent-filter> 
     </activity> 

ReceivingActivity

if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) { 
    string appName = null; 
    // Resolve intent 
    if (getIntent().getAction().equals(ACTION_VERIFY) {  
     int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1); 
     if (-1 != mAppPid) { 
      appName = Utils.getAppNameByPID(mContext, mAppPid); 
     } 
     if (null != appName && !"".equalsIgnoreCase(appName)) { 
       // Do something with the application package name 
     } 
    } 
} 

Utils Klasse

public static String getAppNameByPID(Context context, int pid){ 
     ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 

     for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { 
      if (processInfo.pid == pid) { 
       return processInfo.processName; 
      } 
     } 
     return ""; 
    } 
Verwandte Themen