无法从其他应用程序访问 customProvider。它说它缺少它已经拥有的权限
Can't access a customProvider from another app. It says it's missing permissions it already has
我正在尝试制作一个应用程序,该应用程序可以从另一个具有自定义内容提供程序的应用程序访问 SQLite table。我收到以下错误:
java.lang.SecurityException: Permission Denial: reading com.example.carlos.gymlog.MiContentProvider uri content://mi.uri.porquesi/sesiones from pid=2375, uid=10064 requires android.permission.permRead, or grantUriPermission()
但是,我的 "sender" 应用程序(带有数据库的应用程序)已经具有所需的权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.carlos.gymlog" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MiTema" >
<activity
android:name=".Principal"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:name="MiContentProvider"
android:authorities="mi.uri.porquesi"
android:readPermission="android.permission.permRead"
android:exported="true"
android:grantUriPermissions="true"> </provider>
</application>
</manifest>
这是导致 "receiver" 应用程序(试图访问另一个应用程序)中的错误的代码:
ArrayList<Sesion> sacarDatos(Context c){
Uri cUri = Uri.parse("content://mi.uri.porquesi/sesiones");
ContentProviderClient miCP = c.getContentResolver().acquireContentProviderClient(cUri);
ArrayList<Sesion> sesiones = null;
try {
Cursor cur = miCP.query(cUri, null, null, null, null);
sesiones = new ArrayList<Sesion>();
cur.moveToFirst();
Sesion sesion = null;
do {
sesion = new Sesion(cur.getInt(0),cur.getInt(1),cur.getInt(2),cur.getInt(3));
sesiones.add(sesion);
} while (cur.moveToNext());
} catch (RemoteException e) {
e.printStackTrace();
}
return sesiones;
}
最后,这是我的自定义内容提供商:
public class MiContentProvider extends android.content.ContentProvider {
private static final String uri = "content://mi.uri.porquesi";
public static final Uri CONTENT_URI = Uri.parse(uri);
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
BaseDatosHelper miBD = new BaseDatosHelper(getContext(), "SESIONES", null, 1);
SQLiteDatabase db = miBD.getWritableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("SESIONES");
Cursor cur = qb.query(db,projection,selection,selectionArgs,"","",sortOrder);
cur.setNotificationUri(getContext().getContentResolver(),uri);
return cur;
}
(其余方法如 insert() 未实现,它们只是 return null 或其他任何内容,我只想 select 数据不插入它)。
编辑:
我的应用 A 有
<provider android:name="MiContentProvider"
android:authorities="mi.uri.porquesi"
android:exported="true"
android:permission="mi.permision"
android:grantUriPermissions="true"> </provider>
<permission
android:name="mi.permision"
/>
(只是一个随机的临时名称)
在应用程序 B 中,我添加了
<uses-permission android:name="mi.permision"/>
但是,现在我得到:
java.lang.SecurityException: Permission Denial: opening provider com.example.carlos.gymlog.MiContentProvider from ProcessRecord{335efe6e 3116:com.example.carlos.sample/u0a67} (pid=3116, uid=10067) requires mi.permision or mi.permision
所以它识别出我需要我的自定义权限,但它没有识别出我的应用程序 B 正在使用它。为什么??
假设我们有应用程序 A 和应用程序 B。应用程序 A 有 ContentProvider
;应用程序 B 想要使用来自应用程序 A 的 ContentProvider
。并且,您想要使用自定义权限保护 ContentProvider
。
应用程序 A 需要在其清单中使用 a <permission>
element,并在 android:name
属性中使用您的自定义权限名称。 不要 在该自定义权限名称上使用 android.permission
前缀,因为您不是 Android 开源项目的开发人员。为您的应用使用命名空间,例如 com.kace91.permission.AND_REMEMBER_THAT_CUSTOM_PERMISSIONS_HAVE_SECURITY_ISSUES
.
App A 然后需要 the <provider>
manifest element 上的一个属性,该属性的值与 <permission>
元素的 android:name
属性的名称相匹配。要么使用android:permission
防御所有操作,要么拥有两个自定义权限并使用android:readPermission
和android:writePermission
。 不要 简单地使用android:readPermission
,因为这意味着任何应用程序都可以在未经许可的情况下修改ContentProvider
,而且这不太可能是用户想要的。
应用程序 A 还需要 <provider>
元素上的 android:exported="true"
属性,表示第三方应用程序可以启动与该 ContentProvider
的通信。
App B 可以拥有 a <uses-permission>
manifest element,其 android:name
属性值与 App A 的 <permission>
元素的 android:name
属性相匹配。如果您使用了两个权限,对于读写,App B 需要两个 <uses-permission>
元素。
那么,如果App A先于App B安装,并且用户同意授予App B持有自定义权限,那么App B就可以对App A的ContentProvider
执行指定的操作。
而且,正如我在评论中指出的那样,there are security issues with custom permissions。
我正在尝试制作一个应用程序,该应用程序可以从另一个具有自定义内容提供程序的应用程序访问 SQLite table。我收到以下错误:
java.lang.SecurityException: Permission Denial: reading com.example.carlos.gymlog.MiContentProvider uri content://mi.uri.porquesi/sesiones from pid=2375, uid=10064 requires android.permission.permRead, or grantUriPermission()
但是,我的 "sender" 应用程序(带有数据库的应用程序)已经具有所需的权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.carlos.gymlog" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MiTema" >
<activity
android:name=".Principal"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:name="MiContentProvider"
android:authorities="mi.uri.porquesi"
android:readPermission="android.permission.permRead"
android:exported="true"
android:grantUriPermissions="true"> </provider>
</application>
</manifest>
这是导致 "receiver" 应用程序(试图访问另一个应用程序)中的错误的代码:
ArrayList<Sesion> sacarDatos(Context c){
Uri cUri = Uri.parse("content://mi.uri.porquesi/sesiones");
ContentProviderClient miCP = c.getContentResolver().acquireContentProviderClient(cUri);
ArrayList<Sesion> sesiones = null;
try {
Cursor cur = miCP.query(cUri, null, null, null, null);
sesiones = new ArrayList<Sesion>();
cur.moveToFirst();
Sesion sesion = null;
do {
sesion = new Sesion(cur.getInt(0),cur.getInt(1),cur.getInt(2),cur.getInt(3));
sesiones.add(sesion);
} while (cur.moveToNext());
} catch (RemoteException e) {
e.printStackTrace();
}
return sesiones;
}
最后,这是我的自定义内容提供商:
public class MiContentProvider extends android.content.ContentProvider {
private static final String uri = "content://mi.uri.porquesi";
public static final Uri CONTENT_URI = Uri.parse(uri);
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
BaseDatosHelper miBD = new BaseDatosHelper(getContext(), "SESIONES", null, 1);
SQLiteDatabase db = miBD.getWritableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("SESIONES");
Cursor cur = qb.query(db,projection,selection,selectionArgs,"","",sortOrder);
cur.setNotificationUri(getContext().getContentResolver(),uri);
return cur;
}
(其余方法如 insert() 未实现,它们只是 return null 或其他任何内容,我只想 select 数据不插入它)。
编辑:
我的应用 A 有
<provider android:name="MiContentProvider"
android:authorities="mi.uri.porquesi"
android:exported="true"
android:permission="mi.permision"
android:grantUriPermissions="true"> </provider>
<permission
android:name="mi.permision"
/>
(只是一个随机的临时名称)
在应用程序 B 中,我添加了
<uses-permission android:name="mi.permision"/>
但是,现在我得到:
java.lang.SecurityException: Permission Denial: opening provider com.example.carlos.gymlog.MiContentProvider from ProcessRecord{335efe6e 3116:com.example.carlos.sample/u0a67} (pid=3116, uid=10067) requires mi.permision or mi.permision
所以它识别出我需要我的自定义权限,但它没有识别出我的应用程序 B 正在使用它。为什么??
假设我们有应用程序 A 和应用程序 B。应用程序 A 有 ContentProvider
;应用程序 B 想要使用来自应用程序 A 的 ContentProvider
。并且,您想要使用自定义权限保护 ContentProvider
。
应用程序 A 需要在其清单中使用 a <permission>
element,并在 android:name
属性中使用您的自定义权限名称。 不要 在该自定义权限名称上使用 android.permission
前缀,因为您不是 Android 开源项目的开发人员。为您的应用使用命名空间,例如 com.kace91.permission.AND_REMEMBER_THAT_CUSTOM_PERMISSIONS_HAVE_SECURITY_ISSUES
.
App A 然后需要 the <provider>
manifest element 上的一个属性,该属性的值与 <permission>
元素的 android:name
属性的名称相匹配。要么使用android:permission
防御所有操作,要么拥有两个自定义权限并使用android:readPermission
和android:writePermission
。 不要 简单地使用android:readPermission
,因为这意味着任何应用程序都可以在未经许可的情况下修改ContentProvider
,而且这不太可能是用户想要的。
应用程序 A 还需要 <provider>
元素上的 android:exported="true"
属性,表示第三方应用程序可以启动与该 ContentProvider
的通信。
App B 可以拥有 a <uses-permission>
manifest element,其 android:name
属性值与 App A 的 <permission>
元素的 android:name
属性相匹配。如果您使用了两个权限,对于读写,App B 需要两个 <uses-permission>
元素。
那么,如果App A先于App B安装,并且用户同意授予App B持有自定义权限,那么App B就可以对App A的ContentProvider
执行指定的操作。
而且,正如我在评论中指出的那样,there are security issues with custom permissions。