I did not find a post which ask for the same restriction as me.
I have an application which provides a content provider (call it main application) to other applications (call them client applications). I want restrict the access to the content provider from the client applications for support only the insert and maybe query methods.
What I do not want:
The most obvious solution I see is to write two content provider, one with full access private of the main application, and one restricted public. But I think this is definitely not a proper way.
According to this Google groups post, I am thinking to use Binder.getCallingUid()
in the content provider calls to detect if the call comes from the main application or not. So I can do nothing in update and delete methods if the call does not come from the main application.
How I can get the main application UID to compare? And if it is possible, is this solution secure?
Thanks for your advice.
A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object.
Content providers can help an application manage access to data stored by itself, stored by other apps, and provide a way to share data with other apps. They encapsulate the data, and provide mechanisms for defining data security.
Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications.
A content URI is a URI that identifies data in a provider. Content URIs include the symbolic name of the entire provider (its authority) and a name that points to a table or file (a path).
Define a permission like below with protectionLevel signature, this WRITE permission will restricted to only apps which are signed with same private key
<permission android:name="com.yourapp.WRITE.PERMISSION"
android:protectionLevel="signature"
android:label="@string/permission_label"
android:description="@string/permission_desc">
</permission>
<permission android:name="com.yourapp.READ.PERMISSION"
android:label="@string/permission_label"
android:description="@string/permission_desc">
</permission>
Then in contentprovider tag use read and write permission tags. You can either enforce read permission or you could altogether remove it
android:readPermission="com.yourapp.READ.PERMISSION"
android:writePermission="com.yourapp.WRITE.PERMISSION"
So only apps that are signed by same signature can use your content provider
Edit:
Maybe you could use this
private Collection<String> getCallingPackages() {
int caller = Binder.getCallingUid();
if (caller == 0) {
return null;
}
return Lists.newArrayList(mContext.getPackageManager().getPackagesForUid(caller));
}
And check if your packagename is present in this list. I think it is safe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With