Android 應用互調的實現並新增自定義許可權進行安全防護
阿新 • • 發佈:2018-11-11
最近在做一個安全漏洞修復的工作,場景是A應用必須由B應用調起,由於涉及到元件暴露所以我們需要考慮安全的問題,最後添加了自定義許可權進行解決。
一、A應用
作為被調起者,需要暴露元件給B應用。所以A的清單檔案中要新增自定義許可權(注意:這裡的許可權級別至少是signature或者signatureOrSystem的,關於許可權的說明以及為什麼這個級別的就安全請檢視此處),並且要給需要暴露的元件設定此許可權。
(1)A應用的清單檔案
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.leeky.a_test_pemisstion_application"> <!--自定義許可權--> <permission android:name="com.bao.permission.SAFE_TEST" android:protectionLevel="signature" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--給暴露的元件設定自定義許可權--> <activity android:name=".AActivity" android:permission="com.bao.permission.SAFE_TEST"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".TestActivity" android:permission="com.bao.permission.SAFE_TEST"> <!-- 給這個activity新增外界訪問這個activity的action屬性,便於android系統查詢 --> <intent-filter> <action android:name="com.leeky.a_test_pemisstion_application.intent.action.Test"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> </application> </manifest>
(2)給兩個Activity設定佈局,為了方便只放了一個標記頁面的TextView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A應用-----Hello World!" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A應用-----Test" /> </LinearLayout>
二、B應用
作為調起者,首先需要宣告A的自定義許可權,不然程式會因為沒有許可權而奔潰。然後在Activity類中寫跳轉到A應用某一頁面的程式碼(這裡提供了setComponent跳轉和利用action兩種方式)。
(1)B應用的清單檔案
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.leeky.b_test_permission_application">
<!--B應用申明A應用許可權-->
<uses-permission android:name="com.bao.permission.SAFE_TEST" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
(2)B應用主頁面兩種跳轉的實現
package com.leeky.b_test_permission_application;
import android.content.ComponentName;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button mButton,mButton2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton=findViewById(R.id.buttonPanel);
mButton2=findViewById(R.id.buttonPanel2);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//應用間跳轉方式一
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.leeky.a_test_pemisstion_application","com.leeky.a_test_pemisstion_application.AActivity"));
startActivity(intent);
}
});
mButton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//應用間跳轉方式二
Intent intent = new Intent(
"com.leeky.a_test_pemisstion_application.intent.action.Test");
startActivity(intent);
}
});
}
}
(3)B的主頁面佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context=".MainActivity">
<Button
android:id="@+id/buttonPanel"
android:text="跳轉到A應用"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/buttonPanel2"
android:text="跳轉到A應用test頁"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_marginTop="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B----Hello World!"/>
</LinearLayout>
三、最後我想說,這樣實現存在一個問題是:如果調起的入口是啟動頁並且設定了自定義許可權,被調起的A應用無法自己啟動(現象是點選應用圖示沒反應,顯示activity not found或者“應用不存在”)。如果A應用的啟動頁不暴露出去,A是可以自己啟動的;但是好多情況下A的啟動頁恰好是被調起的入口,這樣就尷尬了,目前沒有找到解決辦法,我會及時更新的,也希望大家去琢磨一下為什麼會這樣。