Android 安卓:安全IPC替代AIDL?

Android 安卓:安全IPC替代AIDL?,android,ipc,android-security,android-binder,Android,Ipc,Android Security,Android Binder,我想做的是:在设备上安装的两个应用程序之间实现轻量级的、安全的IPC协议。客户端应用程序应该能够向服务应用程序中运行的服务发送命令和查询,并接收返回的计算结果 应用程序关系:两个应用程序的源代码都在我的控制之下,但应用程序将具有不同的签名(不可协商) 安全要求:服务应用程序应向单个客户端提供服务。客户机的应用程序ID(包名称)是已知的且是常量 我尝试的内容:我尝试使用双向Messenger通信方案实现IPC(类似于)。这种方法工作得很好,但我遇到了一个主要问题——我找不到一种方法来获取客户端的U

我想做的是:在设备上安装的两个应用程序之间实现轻量级的、安全的IPC协议。客户端应用程序应该能够向服务应用程序中运行的
服务
发送命令和查询,并接收返回的计算结果

应用程序关系:两个应用程序的源代码都在我的控制之下,但应用程序将具有不同的签名(不可协商)

安全要求:服务应用程序应向单个客户端提供服务。客户机的应用程序ID(包名称)是已知的且是常量

我尝试的内容:我尝试使用双向
Messenger
通信方案实现IPC(类似于)。这种方法工作得很好,但我遇到了一个主要问题——我找不到一种方法来获取客户端的
UID
,因此我无法满足安全性要求

考虑服务应用程序的
服务
中的此代码:

// This messenger will be used by the clients of this service in order to send commands
private Messenger inboxMessenger = new Messenger(new Handler() {

    @Override
    public void handleMessage(Message msg)

        // TODO: verify the identity of the client

        switch (msg.what) {
            case MSG_GET_DATA:
                returnDataToClient(msg.replyTo);
                break;
        }
    }
});
这里的想法是,当客户端应用程序向该
服务发送消息时,它会将其本地“回调”
Messenger
放入已发送
消息的
成员中。
Messenger
的文档说明:

注意:下面的实现只是一个简单的包装器 用于执行通信的活页夹

因此,我认为我可以以某种方式将
Messenger#getBinder()
返回的数据映射到客户端的
UID
,但现在我遇到了一些问题:

  • Messenger#getBinder()
    返回无法强制转换到
    Binder
  • 即使我设法获得对客户端的
    活页夹的引用
    ,方法
    活页夹#getCallingUid()
    也是
    静态的
    ,并且不接受参数 因此,为了使这个特定的实现安全地工作,我需要找到一种方法,根据
    消息的内容或客户端创建的特定
    Messenger
    获取调用方的
    UID
    。由于Android的安全体系结构是围绕
    活页夹
    构建的,因此似乎奇怪的是,没有直接的方法将
    活页夹
    映射到
    UID
    (或包名)。。。那么,我该怎么做呢


    附加问题:除了AIDL,安卓上还有其他IPC技术可以满足上述要求吗?

    经过一些研究和实验,我得出结论,在安全、签名保护的通信方面,安卓无法替代AIDL


    好消息是,AIDL并不难实现,关于这个特定主题的官方教程一点也不差。

    您可以在服务器端检查客户端的签名,以确保它是合格的。

    当您从内部调用static
    getCallingUid()
    时,返回的值是什么?引用,
    getCallingUid()
    “返回分配给向您发送当前正在处理的事务的进程的Linux uid…如果当前线程当前未执行传入事务,则返回其自己的uid”。在这种情况下,由于
    处理程序,我怀疑您将获得自己的UID,但至少值得一试。“Android上是否有其他IPC技术可以满足上述要求?”--请参阅
    getCallingUid()
    从服务的
    onStartCommand()
    返回的内容,由
    startService()触发)
    在客户端上。对于客户端发送的广播,请参见从
    BroadcastReceiver
    onReceive()
    返回的内容。查看
    getCallingUid()
    ContentProvider
    的方法中返回的内容(例如,
    call()
    ),以获取客户端通过
    ContentResolver
    发送的请求。就个人而言,我只使用了基于AIDL的
    .Stub
    中的
    getCallingUid()
    ,但我认为上面的1+应该可以使用。@commonware,实际上,从
    handleMessage()内部调用
    getCallingUid()
    返回服务的“自己的”
    UID
    。明天我将测试您建议的其他方法并提供反馈。@Commonware,我尝试在所有
    服务
    生命周期回调中测试
    getCallingUid()
    onCreate()
    onStartCommand()
    onBind()
    )-所有这些方法都返回了“自己的”
    UID
    。也许您建议的其他方法中的一种会起作用,但即使是这样,它们也会使事情变得不直观,并可能造成潜在的性能瓶颈(这只是我的猜测)。所以,我想,我最好开始编写AIDL合同……您是否考虑过使用活页夹作为服务器向客户机发出的令牌,然后作为每个后续客户机请求的一部分?活页夹在所有流程中都是唯一的,因此可以(并且是)作为安全身份与包名/签名结合使用。我正在寻找一种获得签名的方法-如果我可以拥有它,那么我不会问这个问题。你有谷歌!