SecurityException:调用者uid XXXX与authentication者的uid不同

尝试实现Sample Sync Adapter应用程序时,收到上述exception。 我看到很多与这个问题有关的post,但是没有得到满意的答复。

所以我会在这里记下我的解决scheme ,以防其他人遇到同样的问题。

一些其他有用的技巧来debugging这样的问题。

首先启用一些标签的详细日志logging:

$ adb shell setprop log.tag.AccountManagerService VERBOSE $ adb shell setprop log.tag.Accounts VERBOSE $ adb shell setprop log.tag.Account VERBOSE $ adb shell setprop log.tag.PackageManager VERBOSE 

你会看到这样的日志logging:

 V/AccountManagerService: initiating bind to authenticator type com.example.account V/Accounts: there is no service connection for com.example.account V/Accounts: there is no authenticator for com.example.account, bailing out D/AccountManagerService: bind attempt failed for Session: expectLaunch true, connected false, stats (0/0/0), lifetime 0.002, addAccount, accountType com.example.account, requiredFeatures null 

这意味着没有为此帐户types注册authentication者。 要查看哪些authentication程序已注册,请在安装软件包时观看日志:

 D/PackageManager: encountered new type: ServiceInfo: AuthenticatorDescription {type=com.example.account}, ComponentInfo{com.example/com.example.android.AuthenticatorService}, uid 10028 D/PackageManager: notifyListener: AuthenticatorDescription {type=com.example.account} is added 

我有问题的身份validationXML描述符引用一个string资源,在安装过程中没有得到正确解决:

 android:accountType="@string/account_type" 

日志显示

 encountered new type: ServiceInfo: AuthenticatorDescription {type=@2131231194}, ... 

用一个普通的string(不是资源)replace它解决了这个问题。 这似乎是Android 2.1的具体。

 android:accountType="com.example.account" 

首先,检查在这个职位上解释的条件:

[…]如果您从caller uid XXXX is different than the authenticator's uidAccountManagerService中看到错误caller uid XXXX is different than the authenticator's uid ,则可能有点误导。 该消息中的“身份validation器”不是您的身份validation器类,它是Android可以识别的帐户types的注册身份validation器。 在AccountManagerService中发生的检查如下所示:

  private void checkCallingUidAgainstAuthenticator(Account account) { final int uid = Binder.getCallingUid(); if (account == null || !hasAuthenticatorUid(account.type, uid)) { String msg = "caller uid " + uid + " is different than the authenticator's uid"; Log.w(TAG, msg); throw new SecurityException(msg); } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid"); } } 

请注意, hasAuthenticatorUid()需要account.type 。 这是我搞砸的地方。 我用一个常量指定的types创build我的Account

  class LoginTask { Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE); ... } class AuthenticatorService extends Service { public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared"; ... } 

但是这个常量与我的validation器的XML定义不匹配:

  <account-authenticator xmlns:android="/web/20150729061818/http://schemas.android.com/apk/res/android" android:accountType="com.joelapenna.foursquared.account" ... /> 

其次,如果你像我一样,想要将样本embedded到现有的应用程序中进行testing,那么请确保使用属于本示例的一部分的Constants类而不是android.provider.SyncStateContract包。 因为这两个类都使用创buildAccount对象时使用的相同属性名称ACCOUNT_TYPE

在我的情况下,问题是非常简单地在res/xml/authenticator.xml声明的android:accountType="com.foo"的不匹配为android:accountType="com.foo"但在创build帐户时被错误地称为"foo.com"

 Account newAccount = new Account("dummyaccount", "foo.com"); 

卫生署!

有几个部分来实现自定义帐户…

要在您的活动中调用AccountManager,就像您已经实现的那样…

 Account account = new Account(username, ACCESS_TYPE); AccountManager am = AccountManager.get(this); Bundle userdata = new Bundle(); userdata.putString("SERVER", "extra"); if (am.addAccountExplicitly(account, password, userdata)) { Bundle result = new Bundle(); result.putString(AccountManager.KEY_ACCOUNT_NAME, username); result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCESS_TYPE); setAccountAuthenticatorResult(result); } 

在res / xml / authenticator.xml中,您必须定义您的AccountAuthenticator数据(负责您的Authenticator UID)。 ACCESS_TYPE必须与您在此xml中定义的accountType相同的string!

 <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="de.buecherkiste" android:icon="@drawable/buecher" android:label="@string/app_name" android:smallIcon="@drawable/buecher" > </account-authenticator> 

最后,你必须定义你的服务你的清单。 请不要忘记pipe理您的帐户的相关权限(AUTHENTICATE_ACCOUNTS / USE_CREDENTIALS / GET_ACCOUNTS / MANAGE_ACCOUNTS)

 <service android:name=".AuthenticationService"> <intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service> 

我的错误是假设AccountManager的getAccounts()方法返回只与我的应用程序上下文相关联的帐户。 我改变了

 AccountManager accountManager = AccountManager.get(context); Account[] accounts = accountManager.getAccounts(); 

 AccountManager accountManager = AccountManager.get(context); Account[] accounts = accountManager.getAccountsByType(Constants.ACCOUNT_TYPE); 

如果您在清单中的意图filter中input了不正确的值,则会出现相同的错误。 我经历了同步适配器上的android-dev教程,并最终为“intent-filter / action android:name”以及“meta-data / android:name”为syncadapter / accountauthenticator设置了一个伪造的值。 这个错误导致了相同的错误出现在日志中。

为了logging,正确的值是:{android.content.SyncAdapter,android.accounts.AccountAuthenticator}

确保您的服务XML指向正确的位置。

例如,如果你是模块名称是

com.example.module.auth

你的服务android:name应该是

 <service android:name=".module.auth.name-of-authenticator-service-class"... 

在AndriodManifest.xml中

首先,看看Jan Berkel出色的debuggingbuild议。

最后,要检查的另一件事是你的内容提供者和authentication以及同步服务被声明为application标签的子代。

  <application ...> <activity ...(Activity)... </activity> <provider ...(CP service declaration)/> <service ...(Authentication service declaration)... </service> <service ...(Sync service declaration)... </service> </application> 

对我来说这是一个非常愚蠢的错误,很难find。

我在authenticator.xml中写道

 <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.myapp" android:icon="@drawable/ic_launcher" android:smallIcon="@drawable/ic_launcher" android:label="@string/app_name" /> 

代替

 <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.myapp" android:icon="@drawable/ic_launcher" android:smallIcon="@drawable/ic_launcher" android:label="@string/app_name" /> 

这是造成这个错误。 希望这可以帮助别人!

在我的情况下,这是我的清单文件的权限

 <uses-permission android:name="ANDROID.PERMISSION.GET_ACCOUNTS"/> 

这是全部大写,当我改变它

 <uses-permission android:name="android.permission.GET_ACCOUNTS"/> 

问题没有了

也,

检查一下,看看你是不是像普通的老string那样对待AccountType。

我有我的大部分代码打包在com.mycompany.android下

我一直使用以下AccountType成功: com.mycompany.android.ACCOUNT

现在我有一个使用多个帐户的愿望,当我尝试在帐户末尾附加“.subType”的方法时,

调用者uid xxxxx与authentication者的uid不同

但是,如果我使用“_subType”(下划线而不是点),它工作正常。

我的猜测是,Android正试图将com.mycompany.android.ACCOUNT作为一个合法的软件包名称,而这肯定不是。

所以,再次:

BAD com.mycompany.android.ACCOUNT.subType

好的 com.mycompany.android.ACCOUNT_subType

如果你得到这个错误,以上所有的解决scheme都不适合你。 另外,你认为你已经遵循了所有的程序。 身份validation服务可能是由其他开发人员开发的,您希望使用它来添加帐户。

您可以尝试的是尝试使用发行密钥库对您的应用程序进行签名。 现在你运行该应用程序。 我想这应该适合你。

这是另一个可能的解决scheme。

当我的用户在我的应用程序中注册与他的Android谷歌帐户相同的电子邮件时,我有这个错误。

所以,当我试图accountManager.getAccounts()和search这个电子邮件时,我发现一个帐户使用相同的电子邮件,但与另一个帐户types。 所以,当试图使用这个(google.com)帐户时,我得到这个错误。

所以,find一个帐户的正确方法是:

 public Account findAccount(String accountName) { for (Account account : accountManager.getAccounts()) if (TextUtils.equals(account.name, accountName) && TextUtils.equals(account.type, "myservice.com")) return account; return null; } 

还要确保您的AccountAuthenticatorService具有certificate者意图filter;

即。

 <service android:name=".service.AccountAuthenticatorService"> <intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service> 

如果在三星设备上出现此exception,请确保您没有使用安全模式 。

如果相同的应用程序来自不同的商店,例如亚马逊应用程序商店和谷歌Play商店,最终的安全性exception将被抛出,因为在这种情况下应用程序的签名将是不同的。如果你计划使用相同的身份validation器login,任一应用程序将崩溃。 我曾经遇到过这个麻烦。 特别是亚马逊的app store会为了安全的目的而用自己的签名来签署它的应用程序。

注意:如果没有input错误或其他答案,请在单点login时检查应用程序的签名。

对于那些仍然遇到问题的人: https ://stackoverflow.com/a/37102317/4171098

在我的情况下,我无意中在<application>标签之外的Manifest中定义了AuthenticatorService。 移动<application>的声明修复了这个问题。 希望会帮助别人。