Android中的IntentFilter與安全

技術小甜發表於2017-11-09
 
 
Intent是Android應用程式核心元件之間通訊和傳遞資訊的核心機制。與之相關的IntentFilter也具有相關的安全機制(測試)來進行約束。本文將對其進行詳細介紹。
 
一、Intent和IntentFilter簡介
一個應用程式的三個核心元件(活動,服務和廣播接收器)都是通過訊息即意圖(Intents)來啟用的。Intent訊息傳送是相同或不同應用中元件執行時晚繫結的一種機制。意圖本身(一個意圖物件)是一個包含被執行操作抽象描述的被動的資料結構。或,對於廣播而言,是某件已經發生並被宣告的事情的描述。存在如下幾種不同的機制來傳送意圖到每種元件中:
在每個例子裡,Android系統找到合適的活動、服務或者一組廣播接收者來回應這個意圖,必要時例項化它們。這些訊息傳送系統沒有重疊:廣播意圖僅被傳遞給廣播接收者,永遠不會給活動或者服務。一個傳送給startActivity()的意圖是隻會被傳遞給一個活動,永遠不會給一個服務或廣播接收者,如此類推。
為了通知系統它們可以處理哪些意圖,活動、服務和廣播接收器可以有一個或多個意圖過濾器。每個過濾器描述元件的一個能力,一系列元件想要接收的意圖。它實際上按照一個期望的型別來進行意圖濾入,同時濾出不想要的意圖-但是隻有不想要的隱式意圖會被濾出(那些沒有命名目標的物件類)。一個顯式意圖總能夠被遞交給它的目標,而無論它包含什麼。這種情況下過濾器不起作用。但是一個顯式意圖僅當它能通過元件的一個過濾器時才可以被遞交到這個元件。
元件為它能做的每項工作,每個呈現給使用者的不同方面分有不同的過濾器。比如,範例記事本應用程式中的主要活動有三個過濾器:一個是空白板,另一個是使用者可以檢視、編輯、或選擇的一個指定的記事目錄,第三是在沒有初始目錄說明的情況下查詢一個特定的記錄。一個意圖過濾器是IntentFilter類的一個例項。但是,由於Android系統在啟動一個元件前必須知道這個元件的能力,意圖過濾器通常不會用Java程式碼來設定,而是在應用程式清單檔案(AndroidManifest.xml)中設定<intent-filter>元素。(有一個例外,通過呼叫Context.registerReceiver()來註冊的廣播接收器的過濾器;它們是作為意圖過濾器物件而被直接建立的。
 
 
二 、過濾器與安全Filters and security
我們不能信賴一個意圖過濾器的安全性。當它開啟一個元件來接收某些特定型別的隱式意圖,它並不能阻止以這個元件為目標的顯式意圖。即使過濾器對元件要處理的意圖限制某些動作和資料來源,總有人能把一個顯式意圖和一個不同的動作及資料來源組合在一起,然後命名該元件為目標。
一個過濾器和意圖物件有同樣的動作、資料以及類別欄位。一個隱式意圖在過濾器的所有三個方面都被測試。為了遞交到擁有這個過濾器的元件,它必須通過所有這三項測試。即便只有一個不通過,Android系統都不會把它遞交給這個元件。不過,由於一個元件可以包含多個意圖過濾器,一個不能通過其中一個元件過濾器的意圖可能在另外的過濾器上獲得通過。
與之相關的三個測試詳細描述如下:
測試一:動作測試(Actiontest
清單檔案中的意圖過濾器元素裡列舉了動作元素,比如:

  1. <intent-filter. . . >
  2. <action android:name=“com.example.project.SHOW_CURRENT” />
  3. <action android:name=“com.example.project.SHOW_RECENT” />
  4. <action android:name=“com.example.project.SHOW_PENDING” />
  5. . . .
  6. </intent-filter>
如同例子所示,一個意圖物件只對單個動作命名,而一個過濾器可能列舉多個。列表不能為空;一個過濾器必須包含至少一個動作元素,否則它將阻塞所有的意圖。
為了通過這個測試,在意圖物件中指定的動作必須匹配過濾器中所列舉的動作之一。如果意圖物件或過濾器不指定一個動作,結果將是:如果這個過濾器沒有列出任何動作,那意圖就沒有什麼可匹配的,因此所有的意圖都會測試失敗。沒有意圖能夠通過這個過濾器。另一方面,一個未指定動作的意圖物件自動通過這個測試-只要過濾器包含至少一個動作。
測試二:類別測試(Categorytest
一個意圖過濾器<intent-filter>元素也列舉了類別作為子元素。比如:

  1. <intent-filter. . . >
  2. <category android:name=“android.intent.category.DEFAULT” />
  3. <category android:name=“android.intent.category.BROWSABLE” />
  4. . . .
  5. </intent-filter>
注意前面描述的動作和類別常量沒有在清單檔案中使用。相反使用了完整的字串。比如,對應於前述CATEGORY_BROWSABLE常量,上面的例子裡使用了”android.intent.category.BROWSABLE”字串。類似的,字串”android.intent.action.EDIT” 對應於ACTION_EDIT常量。
對一個通過類別測試的意圖,每個意圖物件中的類別必須匹配一個過濾器中的類別。這個過濾器可以列舉另外的類別,但它不能遺漏任何在這個意圖中的類別。
因此,原則上一個沒有類別的意圖物件應該總能夠通過測試,而不管過濾器裡有什麼。絕大部分情況下這個是對的。但有一個例外,Android把所有傳給startActivity()的隱式意圖當作他們包含至少一個類別:”android.intent.category.DEFAULT”(CATEGORY_DEFAULT常量)。 因此,想要接收隱式意圖的活動必須在它們的意圖過濾器中包含”android.intent.category.DEFAULT”。,而帶”android.intent.action.MAIN”和”android.intent.category.LAUNCHER”設定的過濾器是例外。它們標記那些啟動新任務和呈現在啟動螢幕的活動。它們可以在類別列表中包含”android.intent.category.DEFAULT”,但不是必要的。
測試三:資料測試(Data test
就像動作和類別,一個意圖過濾器的資料規格被包含在一個子元素中。而且這個子元素可以出現多次或一次都不出現。例如:

  1. <intent-filter. . . >
  2. <data android:type=“video/mpeg” android:scheme=“http” .. . />
  3. <data android:type=“audio/mpeg” android:scheme=“http” .. . />
  4. . . .
  5. </intent-filter>
每個資料<data>元素可以指定一個URI和一個資料型別(MIME媒體型別)。有一些單獨的屬性-模式,主機,埠和路徑-URI的每個部分:
scheme://host:port/path
比如,在下面的URI裡面,
content://com.example.project:200/folder/subfolder/etc
模式是”內容”,主機是”com.example.project”,埠是”200″,路經是”folder/subfolder/etc”。主機和埠一起組成URI鑑權(authority);如果未指定主機,埠會被忽略。
這些屬性都是可選的,但彼此有依賴關係:一個授權要有意義,必須指定一個模式。一個路經要有意義,必須同時指定模式和鑑權。
當一個意圖物件中的URI被用來和一個過濾器中的URI規格比較時,它實際上比較的是上面提到的URI的各個部分。比如,如果過濾器僅指定了一個模式,所有那個模式的URIs和這個過濾器相匹配;如果過濾器指定了一個模式、鑑權但沒有路經,所有相同模式和鑑權的URIs可以匹配上,而不管它們的路經;如果過濾器指定了一個模式、鑑權和路經,只有相同模式、鑑權和路經的URIs可以匹配上。當然,一個過濾器中的路徑規格可以包含萬用字元,這樣只需要部分匹配即可。
資料<data>元素的型別屬性指定了資料的MIME型別。這在過濾器裡比在URI裡更為常見。意圖物件和過濾器都可以使用一個”*”萬用字元指定子型別欄位-比如,”text/*”或者”audio/*”-指示任何匹配的子型別。
資料測試同時比較意圖物件和過濾器中指定的URI和資料型別。規則如下:
1) 一個既不包含URI也不包含資料型別的意圖物件僅在過濾器也同樣沒有指定任何URIs和資料型別的情況下才能通過測試。
2) 一個包含URI但沒有資料型別的意圖物件僅在它的URI和一個同樣沒有指定資料型別的過濾器裡的URI匹配時才能通過測試。這通常發生在類似於mailto:和tel:這樣的URIs上:它們並不引用實際資料。
3) 一個包含資料型別但不包含URI的意圖物件僅在這個過濾器列舉了同樣的資料型別而且也沒有指定一個URI的情況下才能通過測試。
4) 一個同時包含URI和資料型別(或者可從URI推斷出資料型別)的意圖物件可以通過測試,如果它的型別和過濾器中列舉的型別相匹配的話。如果它的URI和這個過濾器中的一個URI相匹配或者它有一個內容content:或者檔案file: URI而且這個過濾器沒有指定一個URI,那麼它也能通過測試。換句話說,一個元件被假定為支援content:和file: 資料如果它的過濾器僅列舉了一個資料型別。
如果一個意圖可以通過不止一個活動或服務的過濾器,使用者可能會被詢問要啟用那個元件,並且,如果沒有發現目標物件將會出現異常。

本文轉自samsunglinuxl51CTO部落格,原文連結:http://blog.51cto.com/patterson/940924 ,如需轉載請自行聯絡原作者


相關文章