如何在 Android 中使用自定义权限?

Posted

技术标签:

【中文标题】如何在 Android 中使用自定义权限?【英文标题】:How to use custom permissions in Android? 【发布时间】:2012-02-07 15:39:45 【问题描述】:

我有两个应用程序。

一个是声明权限并拥有单个Activity

AndroidManifest.xml 的一部分

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:permission="your.namespace.permission.TEST" >
    <activity
        android:name=".DeclaringPermissionActivity"
        android:label="@string/app_name" >

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <intent-filter> 
         <action android:name="android.intent.action.VIEW" /> 
         <category android:name="android.intent.category.DEFAULT" /> 
         <category android:name="android.intent.category.BROWSABLE" /> 
         <data android:scheme="myapp"
             android:host="myapp.mycompany.com" /> 
        </intent-filter> 
    </activity>
</application>

第二个声明是使用权限

AndroidManifest.xml 的一部分

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="your.namespace.permission.TEST" />

<application

Activity的一部分:

public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("myapp://myapp.mycompany.com/index")));

我正在安装声明权限的应用程序,然后运行第二个应用程序。

结果我得到安全异常:

 01-11 09:46:55.249: E/AndroidRuntime(347): java.lang.RuntimeException: Unable to start activity ComponentInfoyour.namespace2/your.namespace2.UsingPErmissionActivity: java.lang.SecurityException: Permission Denial: starting Intent  act=android.intent.action.VIEW dat=myapp://myapp.mycompany.com/index cmp=your.namespace/.DeclaringPermissionActivity  from ProcessRecord407842c0 347:your.namespace2/10082 (pid=347, uid=10082) requires your.namespace.permission.TEST

【问题讨论】:

我只想指出这个漏洞:commonsware.com/blog/2014/02/12/… 关于上述漏洞注释,请注意 Android 5.0 中解决此问题的更改:developer.android.com/about/versions/… developer.android.com/guide/topics/permissions/defining 【参考方案1】:

我创建了一个测试代码,您可以使用它并测试您的权限。有两个应用程序 PermissionTestClient 声明权限并使用此权限保护其活动。这是它的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.testpackage.permissiontestclient"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <permission android:name="com.testpackage.mypermission" android:label="my_permission" android:protectionLevel="dangerous"></permission>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:permission="com.testpackage.mypermission"
            android:name=".PermissionTestClientActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter >
                <action android:name="com.testpackage.permissiontestclient.MyAction" />
                <category android:name="android.intent.category.DEFAULT" />                
            </intent-filter>
        </activity>
    </application>

</manifest>

Activity文件没有什么特别的,这里就不展示了。

PermissionTestServer 应用程序从 PermissionTestClient 调用活动。这是它的清单文件:

<?xml version="1.0" encoding="utf-8"?>

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="com.testpackage.mypermission"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name=".PermissionTestServerActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

和活动:

package com.testpackage.permissiontestserver;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class PermissionTestServerActivity extends Activity 
    private static final String TAG = "PermissionTestServerActivity";

    /** Called when the activity is first created. */
    Button btnTest;
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button) findViewById(R.id.btnTest);
        btnTest.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View v) 
                Log.d(TAG, "Button pressed!");
                Intent in = new Intent();
                in.setAction("com.testpackage.permissiontestclient.MyAction");
                in.addCategory("android.intent.category.DEFAULT");
                startActivity(in);
            
        );
    

要测试它,只需从服务器应用程序中删除使用权限。您将收到安全违规错误。

【讨论】:

谢谢,我的错误是将permission 属性只添加到&lt;application&gt; 元素。 当我在 PermissionTestClient 中使用 android:protectionLevel="signature" 时,这对我不起作用,我使用该应用启动器上的权限并获得:权限拒绝:启动 Intent act=android.intent .action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=my.package.foobar/.DashboardActivity from null (pid=4070, uid=2000) 需要 my.custom.permission.ACCESS_ACTIVITY - 所以该应用无法启动它自己的 Activity 0_o 签名权限级别意味着您的客户端和服务器应该使用相同的证书进行签名。尝试使用危险级别启动代码,如果一切正常,然后尝试使用签名启动。还有一件事,如果您使用签名,我认为您需要导出已签名的 apk 文件,然后安装它们。 我想通知大家一个与使用自定义权限相关的安全漏洞。请参阅此公共软件帖子:commonsware.com/blog/2014/02/12/… 不要忘记在定义自定义权限时添加android:description = "string resource" 属性,这将有助于在棉花糖中明确请求权限【参考方案2】:

您需要通过以下方式在基础应用的清单中创建权限 独家声明。例如:

<permission android:name="your.namespace.permission.TEST"
    android:protectionLevel="normal" android:label="This is my custom  permission" />

然后在您想要的应用程序中使用它:

<uses-permission android:name="your.namespace.permission.TEST" />

注意: 保持安装具有自定义权限的应用程序的顺序至关重要。即您必须首先安装声明权限的应用程序,然后再安装使用它的应用程序。此顺序的任何中断都可能会破坏自定义的使用。 权限。

【讨论】:

简明扼要,而且很有效。投票最多的答案更好,但这正是问题中提出的问题。请注意,这是您使用自定义权限所需的全部内容,因为安全管理器会负责其余的工作。 我无法让它工作,即使我在创建权限的应用程序中声明使用权限。它在开始时抛出安全异常 只要我没记错,安装应用程序的顺序也很重要。首先安装声明自定义权限的应用,然后安装使用该自定义权限的应用。 我们可以在创建权限的应用程序中使用自定义权限吗? 这仍然是真的吗?我无法重现安装顺序错误。我已将权限定义 () 放在一个应用程序中。无论我以哪种顺序安装应用程序(我已经为每个测试运行先卸载了这两个应用程序)它总是可以工作 - 至少对于“签名”受保护的权限......【参考方案3】:

如答案中所述,您还应该考虑安装应用程序的顺序。

这很重要,因为:

如果请求权限的应用程序(应用程序B)安装在定义权限的应用程序(应用程序A)之前,那么特定设备中将没有这样定义的权限,因此操作系统不会请求权限完全没有。

稍后,当您安装 App A 并尝试运行 App B 时,后者将无法访问安全组件。

一种解决方法是在应用程序 A 和 B 中定义相同的自定义权限,以确保无论首先安装哪个应用程序,设备中都存在该权限,因此当安装应用程序 A 时,权限将已授予 App B。

但在这种情况下,您应该确保两个声明中的保护级别相同,因为这可能会导致安全风险

(请注意,从 android 5.0 起,您不能在多个应用中定义相同的权限,除非这些应用使用相同的签名密钥进行签名)。

【讨论】:

Android 5.0 及更高版本的任何解决方案,具有不同的登录密钥【参考方案4】:

接受的答案显示了创建自定义权限的正确流程。 我有一些注释可以在我的测试之后决定哪个权限和权限名称

android:protectionLevel="normal" // don't need user confirmation to grant, similar to some low-risk permission like android.permission.INTERNET

android:protectionLevel="dangerous" // need user confirmation to grant // similar to some high-risk permission like android.permission.CAMERA

android:protectionLevel="signature" // both app need to sign with the same signature

在 Android dangerous 权限。 Android 为我们做,我们不需要编码 Android >= 6,用户在使用应用程序时授予dangerous 权限(运行时权限)。我们需要编写代码来请求运行时权限

Android 危险权限名称需要有 2 个部分(在 Android 10、Pixel 4XL 上测试),labeldescriptionicon 不需要使权限工作

<permission
        android:name="my.MyCustomPermission" // work well
        android:name="MyCustomPermission" // not work, the runtime permission dialog won't show
        android:label="" // don't required
        android:description="" // don't required
        android:icon="" // don't required

【讨论】:

【参考方案5】:

使用&lt;Permission&gt; 标签定义自定义权限。 请按照以下链接在应用程序中使用用户定义的权限:

Declaring and Enforcing Permissions

【讨论】:

以上是关于如何在 Android 中使用自定义权限?的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义权限与使用

在 Android 6.0 (sdk 23) 中检查自定义权限

如何对 Android 中的 Activity 强制执行自定义权限?

是否可以使用cordova设置自定义权限请求

android中自定义广播需要哪个权限

如何在 Spring Security 中使用自定义角色/权限?