Android自定义权限

背景

从历史上看,Android自定义权限已经非常混乱,并且依赖于安装顺序,这已知可以揭示漏洞。

在API 21之前,有一个令人不安的解决方法,即在Manifest中声明另一个应用程序的自定义许可,并授予许可...但是,由于API 21,只有一个应用程序可以声明自定义许可并安装另一个应用程序声明同样的许可将被阻止。

替代方法是重新安装需要许可的应用程序,以便它们被系统检测到,但这不是一个好的用户体验。 或者在运行时检查调用应用程序的权限,但这并非没有理论上的缺陷。

问题

从Android Marshmallow(6.0 - API 23)开始,应用程序需要向用户请求许可, 以使用其自定义权限 。 声明的自定义权限不会自动授予。

这看起来很奇怪,因为现在只有一个应用程序可以声明它。

复制

在清单中声明自定义权限和BroadcastReceiver。

<permission
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"
    android:description="@string/control_description"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/control_label"
    android:protectionLevel="normal or dangerous"/>

<uses-permission
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/>

// etc

<receiver
    android:name="com.example.app.MyBroadcastReceiver"
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP">
    <intent-filter android:priority="999">
        <action android:name="com.example.app.REQUEST_RECEIVER"/>
    </intent-filter>
</receiver>

从第三方应用程序声明它使用Manifest中的自定义权限(并通过对话框或设置接受它)并调用:

    final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER");

    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {

        // getResultCode();

        }
    }, null, Activity.RESULT_CANCELED, null, null);

结果将返回CANCELED并且日志将显示:

system_process W / BroadcastQueue:Permission Denial:received Intent {act = com.example.app.REQUEST_RECEIVER flg = 0x10(have extras)} to com.example.app/.MyBroadcastReceiver require for com.example.app.permission.CONTROL_EXAMPLE_APP due to sender com.example.thirdparty

如果我使用标准的ActivityCompat.requestPermissions()对话框来允许用户接受权限,那么接收者就像你所期望的那样工作正常。

这是预期的行为? 或者我忽略了某些东西?

提出一个对话说起来似乎很荒谬

应用示例应用想要使用示例应用的权限

它可能确实关系到用户,给他们提供这样一个无意义的请求。

我当然可以将权限描述和名称更改为他们会接受的内容,例如“与其他已安装的应用程序通信”,但在我叹息并采取该方法之前,我想我会问这个问题。

注意

有序广播的例子是复制问题。 我的应用程序确实使用内容提供者和绑定服务的其他实现。 这不是我需要的替代实施方式,而是对问题的确认。

感谢您阅读这篇文章。

编辑:为了阐明,对于其他实现,例如声明服务的权限(这将是最容易复制的),声明的自定义权限将被自动授予。


据我了解,你试图做下一件事(至少,这是我能够重现你的问题):

  • 您首先声明您的新自定义权限(让我们称它为F)应用程序

    <permission
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"
        android:description="@string/control_description"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/control_label"
        android:protectionLevel="normal or dangerous"/>
    
  • 您可以定义您的F应用使用com.example.app.permission.CONTROL_EXAMPLE_APP权限。 正如指南所言,这是正确的。

    <uses-permission
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/>
    
  • 您在F应用程序中声明您的自定义广播接收器。 要与广播您的应用程序进行通信(无论哪一个,F或其他应用程序)必须获得您的自定义权限

    <receiver
        android:name="com.example.app.MyBroadcastReceiver"
        android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP">
        <intent-filter android:priority="999">
            <action android:name="com.example.app.REQUEST_RECEIVER"/>
        </intent-filter>
    </receiver>
    
  • 您定义第二个(让我们称之为S)应用程序使用com.example.app.permission.CONTROL_EXAMPLE_APP权限。 因为您希望允许S应用向F应用接收者发送广播消息。

    <uses-permission
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/>
    
  • 最后,您尝试使用此代码从您的S应用程序发送广播消息。

    final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER");
    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() {
            @Override
            public void onReceive(final Context context, final Intent intent) {
                // getResultCode();
            }
        }, null, Activity.RESULT_CANCELED, null, null);
    

    而且, 这很重要 ,您已授予您的S应用程序许可权,但您未授权您的F应用程序。

    结果你在F应用程序中声明的广播接收器没有收到任何东西。

  • 在您授予F应用程序许可后(请注意,现在S和F授予您的自定义权限)一切正常。 在F app中声明的广播接收器从S app收到消息。

  • 我想这是正确的行为,因为这个文件告诉我们:

    请注意,在此示例中,DEBIT_ACCT权限不仅用元素声明,还用元素请求它的使用。 您必须请求使用它,以便应用程序的其他组件启动受保护的活动,即使该保护是由应用程序本身施加的。

    而声明权限的应用程序也必须请求相同的权限才能与自己进行通信。

    因此,android API 23应该首先获得使用您的权限表单用户的权限。 我们必须获得2个授予的权限,第一个来自F应用程序(因为guidline表示),第二个来自S应用程序(因为我们只需要访问)。

    但我没有理解你的下一点:

    提出一个对话说起来似乎很荒谬

    应用示例应用想要使用示例应用的权限

    我的原生Android API 23显示了类似这样的内容:

    应用示例应用需要


    我认为你的例子中的问题是,你明确要求你的应用程序被授予自定义权限。

    这部分要求,com.example.thirdparty应用程序有权限:

    <receiver
        android:name="com.example.app.MyBroadcastReceiver"
        android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP">
    

    这部分要求,com.example.app应用程序也有权限:

    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", ...
    

    你提到你在使用服务时没有这个问题。 我不知道你是如何使用这个服务的,但是如果你只是这样声明:

    <service
        android:name="com.example.app.MyService"
        android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP">
    

    然后像这样绑定它:

    context.bindService(serviceIntent, mServiceConnection, ...
    

    那么只要com.example.thirdparty具有授予的权限就足够了,而com.example.app则不需要拥有它。

    换句话说,我认为这种行为是有目的的,并且您在广播和服务行为之间所看到的差异是因为在广播案例中,您特别要求com.example.app具有自定义权限,而在服务案例中,您别。

    我希望我没有误解你的问题。 如果我这样做,请让我知道,我会删除这个回复。


    我认为声明的自定义权限不会被自动授予应用程序是完全正确的。 对于自定义权限具有“正常”或“签名”保护级别的情况,则在安装时授予权限。 否则,如果保护级别是“危险的”,那么它是一个运行时权限,它和其他危险权限一样工作:您将需要提示用户授予应用程序权限。

    链接地址: http://www.djcxy.com/p/14959.html

    上一篇: Android custom permissions

    下一篇: ssh "permissions are too open" error