我在一家生产多个应用程序的公司工作,并非所有这些应用程序具有相同的签名,或者更像是我们暂时拥有至少5-6个应用程序证书。
我们尝试创建一种机制,其中同一设备上的所有公司应用程序共享相同的内容, 例如,如果用户从市场App A安装并且未安装应用程序,则将生成新ID,如果现在他安装应用程序A,则应用程序B应具有与应用程序A相同的ID(id仅是生成的UUID类型#4)等...
我们目前正在使用广播,只有获得我们许可的应用才能接收该广播,并通过另一次广播发送回来(这次是明确的)。 广播和回复都受到我们的签名级别的保护,这当然没有帮助,因为我们有多个签名。
我尝试编写一个意图广播和恢复,它可以拥有自己的保护机制,不仅限于一个签名而是几个,问题是像Binder.getSenderUID()这样的东西不能用于广播和我得到了自己的uid。 看起来我无法获得我的snder的身份,除非他自己在意图中写了他的id,这不是我可以信任的东西,因为它可以很容易伪造。 使用加密需要应用程序附带一个密钥,而不是再次受到保护,转向服务器进行验证需要花费太多时间,并且在移动设备上无法保证成功,因为不是100%确定有网络。
任何人都知道如何从一个应用程序获得另一个应用程序的验证\安全消息?(我的所有应用程序但可能有不同的签名)。
答案 0 :(得分:5)
在这里,如果有任何挑战性问题,我永远不会得到合适的答案!回答,所以我不得不自己找到它。
Intents的问题在于,无法获取发件人,因为他们与发送者地址不重要的网络中的mulicast并行。
如果我希望获得snder的UID,我需要进行“远程”处理,即使他是本地的,而不是使用广播IPC,我需要使用AIDL和IBInder实现。 一旦我有一个Binder对象,我可以在我的服务中调用getCallingUid()并获取调用者的uid,这将允许我让PackageManager给我它的公共证书(不询问过程本身,我问操作系统)并比较它是我在apk中提前准备的一组证书。
另一方的调用应用程序(发送给我ID的另一个进程)只需要使用bindService(service,conn,flags)方法绑定到我。 这种方法的缺点是当然是耗时的过程,Bind需要时间,它是通过内核的异步调用,并不像绑定到本地服务那么快。此外,因为我可能有几个应用程序,我需要同步访问我的内部ID,所以只有第一个没有失败的绑定调用将为我设置和ID。 我仍然需要检查是否可以使用阻止多线程问题的Messanger方法。
希望这有助于其他人。
答案 1 :(得分:2)
很抱歉迟到的回复...
绑定需要时间,更重要的是,它需要异步。 但是,有一种方法可以进行同步绑定 - 当然,假设您尝试联系的服务当时已经开始。 Android为BroadcastReceivers提供了更多功能(它本质上是异步的,因此无法使用普通的bindService),BroadcastReceiver有一个" peekService"方法
如果您想在不收听广播的情况下使用它,您可以这样做:
final IBinder[] b = new IBinder[1];
new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
b[0] = peekService(context, intent);
}
}.onReceiver(context, intent);
IMyInterface i = IMyInterface.Stub.asInterface(b[0);
请注意,您没有绑定到该服务,因此请务必查看每次使用。
答案 2 :(得分:0)
如前所述,绑定可能是解决此问题的最佳方法。但是,您可以考虑切换到Activity而不是BroadcastReceiver,然后您可以使用getCallingActivity()
,假设您使用startActivityForResult()
启动。
按照以下方式声明您的活动以使其成为"沉默"像BroadcastReceiver:
<activity
android:name=".FauxReceiver"
android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:noHistory="true"
>
<intent-filter>
...
</intent-filter>
</activity>
答案 3 :(得分:-1)
我一直在寻找一种方法来验证发送我的intent-filter收到的意图的应用程序的包名称。我的应用程序中处理intent-filter的活动要求intent发送者在Intent Extras字段中包含其进程ID。然后,我的接收活动可以从ActivityManager获取关联的应用程序包名称。
以下是我在通过StackOverflow进行转换时找到的一些示例代码。
两个应用所需的常量
public static final String EXTRA_APP_ID;
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY";
致电活动
Intent verifyIntent = new Intent();
verifyIntent.setAction(Consts.ACTION_VERIFY);
verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid());
// Verify that the intent will resolve to an activity
if (verifyIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY);
} else {
Log.d(TAG, "Application not found.");
}
接收应用
清单
<activity
android:name="com.example.receivingapp.ReceivingActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="com.example.receivingapp.VERIFY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
ReceivingActivity
if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) {
string appName = null;
// Resolve intent
if (getIntent().getAction().equals(ACTION_VERIFY) {
int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1);
if (-1 != mAppPid) {
appName = Utils.getAppNameByPID(mContext, mAppPid);
}
if (null != appName && !"".equalsIgnoreCase(appName)) {
// Do something with the application package name
}
}
}
Utils class
public static String getAppNameByPID(Context context, int pid){
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
return processInfo.processName;
}
}
return "";
}