2016-07-06 160 views
30

背景Android的自定義權限 - 棉花糖

從歷史上看,Android的定製權限have been a messwere install order dependent,這是衆所周知的expose vulnerabilities

在API 21之前,有一個令人不安的解決方法,即在您的Manifest中聲明另一個應用程序的自定義權限,授予權限...但是,由於API 21,只有一個應用程序可以聲明自定義權限,將會阻止聲明相同許可的進一步申請。

替代方法是重新安裝需要權限的應用程序,以便它們被系統檢測到,但該is not a good user experience。或者在運行時檢查調用應用程序的權限,但that is not without its theoretical flaws

問題

就Android棉花糖(6.0 - API 23)的應用程序需要來自用戶的,請求允許使用其自己的自定義權限。聲明的自定義權限不會自動授予。

這看起來很奇特,因爲現在只有一個應用程序可以聲明它。

要複製

聲明自定義權限,並在清單一個BroadcastReceiver。

<permission 
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP" 
    android:description="@string/control_description" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/control_label" 
    android:protectionLevel="normal or dangerous"/> 

<uses-permission 
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 

// etc 

<receiver 
    android:name="com.example.app.MyBroadcastReceiver" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 
    <intent-filter android:priority="999"> 
     <action android:name="com.example.app.REQUEST_RECEIVER"/> 
    </intent-filter> 
</receiver> 

從第三方應用程序,聲明它使用清單中的自定義權限(並通過對話或設置接受),並調用:

final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER"); 

    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() { 
     @Override 
     public void onReceive(final Context context, final Intent intent) { 

     // getResultCode(); 

     } 
    }, null, Activity.RESULT_CANCELED, null, null); 

結果將返回取消和日誌將顯示:

system_process W/BroadcastQueue:權限拒絕:接收意圖{ ACT = com.example.app.REQUEST_RECEIVER FLG = 0×10(具有額外)}至 com.example.app/.MyBroadcastReceiver需要 com.example.app.permission.CONTROL_EXAMPLE_APP由於發件人 com.example.thirdparty

如果我使用標準ActivityCompat.requestPermissions()對話框,允許用戶接受許可,正如你所期望的那樣,接收器能夠正常工作。

問題

這是預期的行爲?或者我忽略了某些東西?

這似乎可笑提出一個對話框說

應用程序示例應用程序要使用的示例應用程序

許可,它可能確實是關注用戶,爲他們提供這樣一個荒謬的請求。

我當然可以將權限描述和名稱改爲他們接受的內容,例如'與其他已安裝的應用程序'進行通信,但在我嘆息並採取該方法之前,我想我會問這個問題題。

有序廣播的例子是複製的問題。我的應用程序確實使用內容提供者和綁定服務的其他實現。這不是我需要的替代實施方式,而是對問題的確認。

感謝您閱讀這篇文章。

編輯:爲了闡明,對於其他實現,例如聲明服務的權限(這將是最容易複製的),自動授予聲明的自定義權限。

+1

FWIW,我無法重現您的問題,至少在Android 7.1(Google Pixel)上。我將你的代碼複製到一個新的Android Studio項目中,並且不會從客戶端向接收者發送廣播並獲得響應。現在,我的示例可能比您的示例更簡單(例如,兩個應用程序都由相同的簽名密鑰簽名)。如果您可以創建一個示例應用程序來持續複製此問題,並且您可以在7.1上對其進行復制,請將[文檔問題](http://b.android.com)與開發人員預覽進行對照,其中包括示例應用程序和完整說明。 – CommonsWare

+0

只是要清楚,你是否要求指導方針如何以合理的方式請求用戶的許可,他不會否認?或者你是否要求在他拒絕你的許可時提出解決方案?我很困惑 –

+0

我認爲,應用程序請求自己的權限的事實可以被解釋爲一個「主開關」,如:「讓其他應用程序控制這個應用程序」。即使必須在第三方應用中授予權限才能控制示例應用,但某些用戶可能實際上正在使用它來完全禁止「可控性」功能。 (但仍然很奇怪,例如服務會自動獲得自定義權限......) – Gyebro

回答

-1

雖然用戶看到在同一應用程序中聲明的應用程序的權限請求可能不明確,但它是自設計以來運行棉花糖的android應用程序。我認爲,從android的角度來看,這種行爲是既定的,也是正確的。

+0

該聲明不可能是正確的,因爲在其他情況下會自動授予「自定義權限」 - 因此它不是「通過設計」 – brandall

0

我想你的例子中的問題是,你明確要求你的應用程序被授予自定義權限。

這部分需要,將com.example.thirdparty程序有權限:

<receiver 
    android:name="com.example.app.MyBroadcastReceiver" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 

而這部分需要,將com.example.app應用程序權限,以及:

context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", ... 

您提到您在使用服務時沒有此問題。我不知道你究竟是如何使用該服務,但如果你只是聲明它是這樣的:

<service 
    android:name="com.example.app.MyService" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 

然後將它綁定這樣的:

context.bindService(serviceIntent, mServiceConnection, ... 

那麼如果com。示例足夠。第三方已授予許可,而com.example.app不需要擁有它。

換句話說,我認爲這是行爲設計​​,並且您在廣播和服務行爲之間所看到的差異是因爲在廣播情況下,您特別要求com.example.app具有自定義權限,而在服務的情況下,你不這樣做。

我希望我沒有誤解你的問題。如果我這樣做,請讓我知道,我會刪除這個回覆。

-2
清單文件

先添加權限後

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
1

我瞭解你嘗試做下一件事(至少,這就是我能夠重現您的問題):

  1. 你首先聲明您的新定製許可(我們稱之爲F)應用程序

    <permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP" 
        android:description="@string/control_description" 
        android:icon="@mipmap/ic_launcher" 
        android:label="@string/control_label" 
        android:protectionLevel="normal or dangerous"/> 
    
  2. 您定義您的F應用使用com.example.app.permission.CONTROL_EXAMPLE_APP權限。正如指南所言,這是正確的。

    <uses-permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 
    
  3. 您在F應用中聲明瞭您的自定義廣播接收器。溝通與廣播你的應用程序(這是無論是哪一個,F或其他應用程序)必須獲得您的自定義權限

    <receiver 
        android:name="com.example.app.MyBroadcastReceiver" 
        android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 
        <intent-filter android:priority="999"> 
         <action android:name="com.example.app.REQUEST_RECEIVER"/> 
        </intent-filter> 
    </receiver> 
    
  4. 您可以定義第二(允許稱之爲S)應用程序使用com.example.app.permission.CONTROL_EXAMPLE_APP許可。因爲您希望允許S應用向F應用接收者發送廣播消息。

    <uses-permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 
    
  5. 最後,您嘗試使用此代碼從您的S應用程序發送廣播消息。

    final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER"); 
    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() { 
         @Override 
         public void onReceive(final Context context, final Intent intent) { 
          // getResultCode(); 
         } 
        }, null, Activity.RESULT_CANCELED, null, null); 
    

    而且,這是重要的,你獲准您的App,但你沒有權限授予您˚F應用。

    因爲在F應用程序中聲明的廣播接收器沒有收到任何東西。

  6. 當您授予您F應用程序的權限(請注意,現在S和F授予您的自定義權限)一切正常。在F app中聲明的廣播接收器從S app收到消息。

我想這是正確的行爲,因爲這doc說我們:

需要注意的是,在這個例子中,DEBIT_ACCT許可不僅 與元素聲明,還要求其使用與 的元素。即使應用程序本身實施了保護,您也必須請求使用該應用程序的其他組件才能啓動受保護的活動 。

而聲明權限的應用程序也必須請求相同的權限才能與自己進行通信。

因此,android API 23應該首先獲得使用您的權限表單用戶的權限。我們必須獲得2個授予的權限,第一個來自F應用程序(因爲guidline表示),第二個來自S應用程序(因爲我們只需要訪問)。

但我不明白你的下一個點:

這似乎可笑提出一個對話框說

應用程序示例應用程序要使用的示例應用程序

許可

我的原生Android API 23顯示了類似這樣的內容:

應用實例應用想要

0

我不認爲這是完全真實的,一個聲明自定義權限將不會自動授權給應用。對於自定義權限具有「正常」或「簽名」保護級別的情況,則在安裝時授予權限。否則,如果保護級別是「危險的」,那麼它是一個運行時權限,它和其他危險權限一樣工作:您將需要提示用戶授予應用程序權限。