1. 程式人生 > >Android 應用互調的實現並新增自定義許可權進行安全防護

Android 應用互調的實現並新增自定義許可權進行安全防護

最近在做一個安全漏洞修復的工作,場景是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的啟動頁恰好是被調起的入口,這樣就尷尬了,目前沒有找到解決辦法,我會及時更新的,也希望大家去琢磨一下為什麼會這樣。