【问题标题】:SecurityException: caller uid XXXX is different than the authenticator's uidSecurityException: caller uid XXXX is different than the authenticationator's uid
【发布时间】:2011-04-16 00:20:46
【问题描述】:

我在尝试实现 Sample Sync Adapter 应用程序时收到上述异常。我看过很多与这个问题相关的帖子,但没有令人满意的回应。

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

【问题讨论】:

  • 谢谢。由于您的帖子,我遇到了这个问题并且能够更快地找到解决方案。
  • 不幸的是,发布的链接在此期间被破坏了。有人有替代品吗?

标签: android


【解决方案1】:

首先,检查this post上解释的条件:

[...] 如果您从AccountManagerService 中看到caller uid XXXX is different than the authenticator's uid 形式的错误,这可能有点误导。该消息中的“身份验证器”不是您的身份验证器类,它是 Android 理解为帐户类型的已注册身份验证器。在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。这就是我搞砸的地方。我正在创建我的Account,其类型由常量指定:

 class LoginTask {
     Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE);
     ...
 }

 class AuthenticatorService extends Service {
     public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared";
     ...
 }

但此常量与我的身份验证器的 XML 定义不匹配:

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

其次,如果您像我一样想要将示例嵌入到您现有的应用程序中进行测试,请确保您使用本示例中的 Constants 类而不是 android.provider.SyncStateContract 包下的类。因为这两个类都使用了相同的属性名称ACCOUNT_TYPE,这在创建Account 对象时使用。

【讨论】:

  • 谢谢!你的第一次检查解决了这个问题。猜猜看,在一个新项目中,我忘记了所有关于身份验证器 xml 文件的信息。!
  • 我仍然看到这个问题,但仅限于我的一些用户。我仔细检查了authenticator.xml 文件中的android:accountType 是否与我的GenericAccountsService 中的常量匹配。我也知道我的绝大多数应用程序用户不会发生此异常,但在我的崩溃日志中,我时不时地看到少数用户的崩溃。任何想法?可以通过某种方式修改authenticator.xml 文件来导致这种情况吗?
  • @clu 您曾经解决过您的问题吗?我面临着相同的情况。这个错误只会出现在我的一小部分用户身上:主要是在 HTC One X、HTC One SV 和 HTC Desire 500 上,以及许多其他设备上。
  • @chandsie 这里也一样。只有 HTC 设备似乎有这个问题。它适用于所有其他设备。
  • @clu 我也面临同样的问题。您是否能够解决此问题或找到其根本原因?
【解决方案2】:

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

首先为某些标签启用详细日志记录:

$ 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

你会看到这样的日志记录:

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

这意味着没有为此帐户类型注册的身份验证器。要查看注册了哪些身份验证器,请在安装包时查看日志:

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

我遇到的问题是身份验证器 xml 描述符引用了在安装过程中未正确解析的字符串资源:

android:accountType="@string/account_type"

日志显示

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

用普通字符串(不是资源)替换它可以解决问题。这似乎是特定于 Android 2.1 的。

android:accountType="com.example.account"

【讨论】:

  • 这帮助我解决了这个问题。
【解决方案3】:

还有,

检查您是否将 AccountType 视为普通旧字符串。

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

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

现在我想使用多个帐户,当我尝试在帐户末尾附加“.subType”的方法时,它失败了

调用者 uid xxxxx 与验证者的 uid 不同

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

我的猜测是,Android 试图将 com.mycompany.android.ACCOUNT 视为合法的包名,但它肯定不是。

所以,再说一遍:

错误 com.mycompany.android.ACCOUNT.subType

com.mycompany.android.ACCOUNT_subType

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

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

      例如,如果您的模块名称是

      com.example.module.auth

      你的服务 android:name 应该是

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

      在 AndriodManifest.xml 中

      【讨论】:

        【解决方案6】:

        还要确保您的 AccountAuthenticatorService 具有证明者意图过滤器;

        即。

        <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>
        

        【讨论】:

          【解决方案7】:

          实现自定义帐户的部分很少...

          要在您的 Activity 中调用 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 相同的字符串!

          <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>
          

          最后,您必须将您的服务定义为您的 Manifest。请不要忘记管理帐户的相关权限(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>
          

          【讨论】:

          • 小心打字错误!身份验证服务。另外,它实际上显然是 name=".AuthenticationService" (带有一个点),在我的情况下它以红色显示,但它仍然有效。
          【解决方案8】:

          在我的情况下,问题很简单,只是在 res/xml/authenticator.xml 中声明为 android:accountType="com.foo" 的 accountType 不匹配,但在创建帐户时被错误地引用为 "foo.com"

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

          哇!

          【讨论】:

          • 嗨,在我的例子中,xml 和 newAccount 对象中的 accountType 都是相同的。仍然显示调用者 uid XXXX 与验证者的 uid 错误不同。为什么?
          【解决方案9】:

          如果您在清单中的意图过滤器中输入不正确的值,也会出现同样的错误。 我浏览了有关同步适配器的 android-dev 教程,最终为同步适配器/帐户身份验证器的“intent-filter/action android:name”和“meta-data/android:name”设置了一个虚假值。此错误导致日志中出现相同的错误。

          作为记录,正确的值是:{android.content.SyncAdapter, android.accounts.AccountAuthenticator}

          【讨论】:

            【解决方案10】:

            首先,再看看 Jan Berkel 出色的调试建议。

            最后,要检查的另一件事是,您的内容提供者、身份验证和同步服务被声明为 application 标记的子代。

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

            【讨论】:

            • 的孩子!为我做的,谢谢!它是
            【解决方案11】:

            如果您收到此错误,并且上述所有解决方案都不适合您。此外,您假设您已遵循所有程序。身份验证服务可能是由其他开发人员开发的,您想利用它来添加帐户。

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

            【讨论】:

              【解决方案12】:

              对我来说,这是一个非常愚蠢的错误,而且很难找到。

              在我写的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"
              />
              

              这是导致此错误的原因。希望这对某人有帮助!

              【讨论】:

                【解决方案13】:

                在我的情况下,它是清单文件中的权限 我有

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

                都是大写的,当我把它改成

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

                问题解决了

                【讨论】:

                  【解决方案14】:

                  这是另一种可能的解决方案。

                  当我的用户使用与他的 android google 帐户相同的电子邮件在我的应用中注册时,我遇到了这个错误。

                  因此,当我尝试accountManager.getAccounts() 并搜索此电子邮件时,我发现了一个具有相同电子邮件但具有另一种帐户类型的帐户。因此,当尝试使用此 (google.com) 帐户时,我收到此错误。

                  所以,找到帐户的正确方法是:

                  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;
                  }
                  

                  【讨论】:

                  • 你可以打电话给accountManager.getAccountsByType("myservice.com")
                  【解决方案15】:

                  如果您在三星设备上遇到此异常,请确保您没有使用 safe mode

                  【讨论】:

                    【解决方案16】:

                    如果相同的应用程序来自不同的商店,例如亚马逊应用商店和谷歌播放商店,最终会引发安全异常,因为在这种情况下应用程序的签名会不同。如果您计划使用相同的身份验证器单点登录的目的,任何一个应用程序都会崩溃。我曾经遇到过这个麻烦。尤其是亚马逊应用商店,出于安全考虑,会使用自己的签名对其应用进行签名。

                    注意:如果这里没有出现拼写错误或其他答案,请在单点登录时检查应用程序的签名。

                    【讨论】:

                      【解决方案17】:

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

                      在我的例子中,我不小心在 Manifest 中定义了 AuthenticatorService 在&lt;application&gt; 标签之外。将声明移到里面 &lt;application&gt; 解决了这个问题。希望能帮助到别人。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2022-12-02
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多