SecurityException: вызывающий UID XXXX отличается от идентификатора аутентификатора
При попытке реализовать приложение Sample Sync Adapter я получил указанное выше исключение. Я видел многочисленные сообщения, связанные с этой проблемой, но не получил удовлетворительного ответа.
Поэтому я изложу здесь свое решение на случай, если кто-то еще столкнется с той же проблемой.
17 ответов
Сначала проверьте условие, описанное в этом посте:
[...] Если вы видите ошибку из 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
объект.
Некоторые другие полезные советы по устранению подобных проблем.
Сначала включите подробное ведение журнала для некоторых тегов:
$ 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"
В моем случае проблема была просто несоответствием в accountType, объявленном в res/xml/authenticator.xml
как android:accountType="com.foo"
но ссылаются неправильно как "foo.com"
при создании учетной записи:
Account newAccount = new Account("dummyaccount", "foo.com");
Doh!
Есть несколько частей для реализации пользовательского аккаунта...
Чтобы вызвать 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 (отвечающие за ваш UID Authenticator). ACCESS_TYPE должен быть той же строкой, что и определенный вами accountType в этом xml!
<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>
Наконец, вы должны определить свой сервис вашего манифеста. Пожалуйста, не забывайте о соответствующих разрешениях для управления своими аккаунтами (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>
Моя ошибка заключалась в том, что метод AccountAanager getAccounts() возвращал учетные записи, связанные только с контекстом моего приложения. Я изменился с
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccounts();
в
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Constants.ACCOUNT_TYPE);
Та же самая ошибка появится, если вы укажете неправильные значения в ваших фильтрах намерений в манифесте. Я прошел учебник по android-dev по sync-адаптерам и в итоге установил фиктивное значение для "intent-filter / action android: name", а также "meta-data / android: name" для syncadapter / accountauthenticator. Эта ошибка вызвала те же ошибки, чтобы появиться в журналах.
Для записи правильные значения: {android.content.SyncAdapter, android.accounts.AccountAuthenticator}
В моем случае это были разрешения в файле манифеста
<uses-permission android:name="ANDROID.PERMISSION.GET_ACCOUNTS"/>
это было все заглавные буквы, когда я изменил его
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
проблема ушла
Убедитесь, что ваш сервис XML указывает на правильное местоположение.
Например, если вы имя модуля
com.example.module.auth
вы сервис андроид: имя должно быть
<service android:name=".module.auth.name-of-authenticator-service-class"...
в AndriodManifest.xml
Прежде всего, взгляните еще раз на превосходные советы по отладке Яна Беркеля.
Наконец, еще одна вещь, которую нужно проверить, это то, что ваш поставщик контента, службы аутентификации и синхронизации объявлены как дочерние элементы application
тег.
<application
...>
<activity
...(Activity)...
</activity>
<provider
...(CP service declaration)/>
<service
...(Authentication service declaration)...
</service>
<service
...(Sync service declaration)...
</service>
</application>
Для меня это была очень глупая ошибка, и ее было очень трудно найти.
В 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"
/>
который был причиной этой ошибки. Надеюсь, это поможет кому-то!
Если вы получаете эту ошибку, и все вышеперечисленные решения не работают для вас. Кроме того, вы предполагаете, что вы выполнили всю процедуру. Может быть шанс, что Служба аутентификации была разработана другим разработчиком, которого вы хотите использовать для добавления учетных записей.
Что вы можете попробовать, так это попробовать подписать ваше приложение с помощью хранилища ключей релиза. Теперь вы запускаете приложение. Я полагаю, это должно работать для вас.
Также,
Проверьте, не слишком ли вы трактуете AccountType как обычный старый тип String.
У меня большая часть кода упакована в com.mycompany.android
Я успешно использовал следующий AccountType: com.mycompany.android.ACCOUNT.
Теперь у меня есть желание использовать несколько учетных записей, и когда я пытаюсь добавить ".subType" в конец моей учетной записи, происходит сбой с
UID вызывающего абонента ххххх отличается от UID аутентификатора
Однако, если я использую "_subType" (подчеркивание вместо точки), он работает нормально.
Я предполагаю, что где-то под капотом Android пытается трактовать com.mycompany.android.ACCOUNT как легальное имя пакета, чего, скорее всего, нет.
Итак, еще раз:
ПЛОХОЙ com.mycompany.android.ACCOUNT.subType
ХОРОШО com.mycompany.android.ACCOUNT_subType
Вот еще одно возможное решение.
У меня была эта ошибка, когда мой пользователь был зарегистрирован в моем приложении с тем же адресом электронной почты, что и его аккаунт Google Android.
Итак, когда я пытался 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;
}
Для тех, кто все еще имеет опыт работы: /questions/24857112/securityexception-pri-popyitke-dobavit-uchetnuyu-zapis/24857135#24857135
В моем случае я случайно определил AuthenticatorService в Манифесте вне
<application>
теги. Перемещение декларации внутри<application>
исправил проблему. Надеюсь, кто-то поможет.
Если вы получаете это исключение на устройствах Samsung, убедитесь, что вы не используете безопасный режим.
Также убедитесь, что ваш 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>
Если одни и те же приложения находятся в разных магазинах, например, в магазине приложений Amazon и магазине Google Play, в конечном итоге будет сгенерировано исключение безопасности, поскольку в этом случае подпись приложений будет другой. Если вы планировали использовать один и тот же аутентификатор в целях войдите, любое из приложений будет зависать. я однажды столкнулся с этой проблемой. Особенно Amazon App Store будет подписывать свои приложения своей собственной подписью в целях безопасности.
Примечание. Если здесь нет ошибок опечаток или других упомянутых здесь ответов, проверьте наличие подписи приложений в случае единого входа.