<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                在前文的分析中,我們略去了CBS中與權限管理相關的部分,本節將集中討論這個問題。先來回顧一下CBS中和權限管理相關的函數調用。 ~~~ //copy方設置ClipData在CBS的setPrimaryClip函數中進行: checkDataOwnerLocked(clip,Binder.getCallingUid()); clearActiveOwnersLocked(); //paste方獲取ClipData在CBS的getPrimaryClip函數中進行: addActiveOwnerLocked(Binder.getCallingUid(), pkg); ~~~ 在分析這3個函數之前,不妨先介紹一下Android系統中的URI權限管理。 1. URI權限管理介紹 Android系統的權限管理中有一類是專門針對URI的,先來看一個示例,該例來自package/providers/ContactsProvider,在它的AndroidManifest.xml中有如下聲明: **AndroidManifest.xml** ~~~ <providerandroid:name="ContactsProvider2" ...... android:readPermission="android.permission.READ_CONTACTS" android:writePermission="android.permission.WRITE_CONTACTS"> ...... <grant-uri-permission android:pathPattern=".*" /> </provider> ~~~ 這里聲明了一個名為“ContactsProvider2“的ContentProvider,并定義了幾個權限聲明,下面對其進行解釋。 - readPermission:要求調用query函數的客戶端必須聲明use-permission為READ_CONTACTS。 - writePermission:要求調用update或insert函數的客戶端必須聲明use-permission為WRITE_CONTACTS。 - grant-uri-permission:和授權有關。 初識grant-uri-permission時,會覺得比較難以理解,現在通過舉例分析幫助讀者加深認識。 - Contacts和ContactProvider這兩個APP都是由系統提供的程序,而且二者關系緊密,所以Contacts一定會聲明READ_CONTACTS和WRITE_CONTACT的權限。如此,Contacts就可以毫無阻礙地通過ContactsProvider來查詢或更新數據庫了。 - 假設Contacts新增一個功能,將ContactsProvider中的某條數據copy到剪切板。根據前面已介紹過的知識可以知道,Contacts會向剪切板中復制一個URI類型的數據。 - 另外一個程序從剪切板中paste這條數據,由于是URI類型的,所以此程序會通過ContentResolver來query該URI所指向的數據。但是這個程序卻并未聲明READ_CONTACTS的權限,所以它query數據時必然會失敗。 或許有人會問,為什么第三個程序不聲明相應權限呢?原因很簡單,第三個程序不知道自己該申明怎樣的權限(除非這兩個程序的開發者能互通信息)。本例ContactsProvider設置的讀權限是READ_CONTACTS,以后可能換成READ_CONTACTS_EXTEND。為了解決類似問題,Android提供了一套專門針對URI的權限管理機制。以這套機制解決示例中權限聲明問題的方法是這樣的:當第三個程序從剪切板中paste數據時,系統會判斷是否需要為這個程序授權。當然,系統不會隨意授權,而是需要考慮ContactsProvider的情況。因為ContactsProvider聲明了grant-uri-permission,并且所paste的URI匹配其中的pathPattern,所以授權就能成功。倘若ContactsProvider沒有聲明grant-uri-permission,或者URI不匹配指定的pathPattern,則授權失敗。 有了前面介紹的權限管理機制,相信下面CBS中的權限管理理解起來就比較簡單了。 感興趣的讀者可閱讀SDK安裝目錄下/docs/guide/topics/security/security.html中關于URI Permission的說明部分。 2. checkDataOwnerLocked函數分析 checkDataOwnerLocked函數的代碼如下: **ClipboardService.java** ~~~ private final void checkDataOwnerLocked(ClipDatadata, int uid) { //第二個參數uid為copy方進程的uid final int N = data.getItemCount(); for(int i=0; i<N; i++) { //為每一個item調用checkItemOwnerLocked checkItemOwnerLocked(data.getItemAt(i), uid); } } // checkItemOwnerLocked函數分析 private final voidcheckItemOwnerLocked(ClipData.Item item, int uid) { if(item.getUri() != null) {//檢查Uri checkUriOwnerLocked(item.getUri(), uid); } Intent intent = item.getIntent(); //getData函數返回的也是一個URI,因此這里實際上檢查的也是URI if(intent != null && intent.getData() != null) { checkUriOwnerLocked(intent.getData(), uid); } } ~~~ 權限檢查就是針對URI的,因為URI所指向的數據可能是系統內部使用或私密的。例如Setting數據中的Secure表,這里的數據不能隨意訪問。雖然直接使用ContentResolver訪問這些數據時系統會進行權限檢查,但是由于目前的剪切板服務也支持URI數據類型,所以這里也需要做檢查,否則惡意程序就能輕松讀取私密信息。 下邊來分析checkUriOwnerLocked函數,其代碼如下: **ClipboardService.java** ~~~ private final void checkUriOwnerLocked(Uri uri,int uid) { ...... longident = Binder.clearCallingIdentity(); boolean allowed = false; try{ /* 調用ActivityManagerService的checkGrantUriPermission函數, 該函數內部將檢查copy方是否能被賦予URI_READ權限。如果不允許, 該函數會拋SecurityException異常 */ mAm.checkGrantUriPermission(uid, null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); }catch (RemoteException e) { }finally { Binder.restoreCallingIdentity(ident); } } ~~~ 根據前面的知識,這里先要檢查copy方是否有讀取URI的權限。下面來分析paste方的權限管理 3. clearActiveOwnersLocked函數分析 clearActiveOwnersLocked函數的代碼如下: **ClipboardService.java** ~~~ private final void addActiveOwnerLocked(int uid,String pkg) { PackageInfo pi; try{ /* 調用PackageManagerService的getPackageInfo函數得到相關信息 然后做一次安全檢查,如果PacakgeInfo的uid信息和當前調用的uid不一致, 則拋SecurityException。這個很好理解,因為paste方可以傳遞虛假的 packagename,但uid是沒法造假的 */ pi = mPm.getPackageInfo(pkg, 0); if (pi.applicationInfo.uid != uid) { throw new SecurityException("Calling uid " + uid + " does not ownpackage " + pkg); } } ...... } //mActivePermissionOwners用來保存已經通過安全檢查的package if(mPrimaryClip != null && !mActivePermissionOwners.contains(pkg)) { //針對ClipData中的每一個Item,都需要調用grantItemLocked來檢查權限 final int N = mPrimaryClip.getItemCount(); for (int i=0; i<N; i++) { grantItemLocked(mPrimaryClip.getItemAt(i), pkg); }//保存package信息到mActivePermissionOwners mActivePermissionOwners.add(pkg); } } //grantItemLocked分析 private final void grantItemLocked(ClipData.Itemitem, String pkg) { if(item.getUri() != null) { grantUriLocked(item.getUri(), pkg); } //和copy方一樣,這里僅檢查URI的情況 Intent intent = item.getIntent(); if(intent != null && intent.getData() != null) { grantUriLocked(intent.getData(), pkg); } } ~~~ 再來看grantUriLocked的代碼: **ClipboardService.java** ~~~ private final void grantUriLocked(Uri uri, Stringpkg) { longident = Binder.clearCallingIdentity(); try{ /* 調用ActivityManagerService的grantUriPermissionFromOwner函數, 注意第二個參數傳遞的是CBS所在進程的uid。該函數內部也會檢查權限。 該函數調用成功后,paste方就被授予了對應URI的讀權限 */ mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(),pkg, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); }catch (RemoteException e) { } finally { Binder.restoreCallingIdentity(ident); } } ~~~ 既然有授權,那么客戶端使用完畢后就需要撤銷授權,這個工作是在setPrimaryClip函數的clearActiveOwnersLocked中完成的。當為剪切板設置新的ClipData時,自然需要將與舊ClipData相關的權限撤銷。讀者可自行分析clearActiveOwnersLocked函數。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看