SecurityException: uid XXXX абонента відрізняється від uid автентифікатора


84

Я отримав вищезазначений виняток під час спроби реалізації програми Sample Sync Adapter. Я бачив численні дописи, пов’язані з цією проблемою, але жодної задовільної відповіді.

Тож я запишу своє рішення тут на випадок, якщо хтось інший потрапить до тієї ж проблеми.


Дякую. Я зіткнувся з цією проблемою і завдяки вашій публікації зміг швидше знайти рішення.
Даміан

4
На жаль, розміщене посилання тим часом зламалося. Хтось має альтернативу?
johsin18

Відповіді:


54

Деякі інші корисні поради щодо налагодження таких проблем.

Спочатку увімкніть детальний журнал для деяких тегів:

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

Це допомогло мені зруйнувати цю проблему.
skygeek

44

Спочатку перевірте умову, пояснену в цій публікації :

[...] Якщо ви бачите помилку 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.!
Джордж Плігоропулос

7
Я все ще бачу цю проблему, але лише для деяких моїх користувачів. Я двічі перевірив, чи відповідає android: accountType у файлі authenticate.xml константі в моєму GenericAccountsService. Я також знаю, що цей виняток не трапляється для переважної більшості користувачів моїх програм, але в моїх журналах аварійного завершення періодично я бачу збій для декількох користувачів. Будь-яка ідея? Чи можна файл Autentiator.xml якось змінити, щоб спричинити це?
b.lit

3
@clu Чи вдалося вам коли-небудь вирішити свою проблему? Я стикаюся з ідентичним сценарієм. Ця помилка виникає лише для невеликої кількості моїх користувачів: здебільшого на HTC One X, HTC One SV та HTC Desire 500, а також на багатьох інших пристроях.
chandsie

1
@chandsie Те саме тут. Здається, ця проблема виникла лише на пристроях HTC. Це чудово працює для будь-якого іншого пристрою.
Кіран Кумар,

@clu Я також стикаюся з такою ж проблемою. Чи змогли ви це вирішити чи знайти першопричину?
wasaig

25

У моєму випадку проблема полягала просто в невідповідності типу accountType, оголошеному res/xml/authenticator.xmlяк, android:accountType="com.foo"але з помилковим посиланням, як "foo.com"при створенні облікового запису:

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

Дох!


1
Привіт, у моєму випадку accountType в xml та в newAccount об’єкт однакові. І все-таки він показує, що uid XXXX абонента відрізняється від помилки uid автентифікатора. чому?
Віджай Ванкхеде

10

Є кілька частин для реалізації власного облікового запису ...

Щоб запустити 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 / authenticate.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>

Слідкуйте за TYPO! AuthenticaTAtionService. Плюс, це насправді name = ". AuthenticationService", мабуть, (з крапкою), і в моєму випадку це відображається червоним, але все одно працює.
FlorianB

5

Моя помилка передбачала, що метод AccountManager getAccounts () повернув облікові записи, лише пов’язані з моїм контекстом програми. Я змінився з

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

до

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

4

Така сама помилка з'явиться, якщо ви внесете неправильні значення у ваші фільтри намірів у своєму маніфесті. Я пройшов підручник для android-dev щодо адаптерів синхронізації і в підсумку встановив фіктивне значення для "intent-filter / action android: name", а також "meta-data / android: name" для syncadapter / accounttauthenticator. Ця помилка спричинила появу тих самих помилок у журналах.

Для запису правильними значеннями є: {android.content.SyncAdapter, android.accounts.AccountAuthenticator}


2

Переконайтеся, що служба XML вказує на правильне розташування.

Наприклад, якщо ви назва модуля

com.example.module.auth

ти сервіс android: ім'я повинно бути

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

у AndriodManifest.xml


2

Спочатку погляньте ще раз на чудові поради щодо налагодження Яна Беркеля.

Нарешті, ще одна справа, яку слід перевірити, - це те, що ваш постачальник вмісту та служби автентифікації та синхронізації оголошені як дочірні елементи applicationтегу.

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

        <service
            ...(Authentication service declaration)...
        </service>

        <service
            ...(Sync service declaration)... 
        </service>
    </application>

Нащадок <застосування>! Зробив це для мене, дякую! І це <service android: name = ". AuthenticationService">
FlorianB

2

Для мене це була дуже дурна помилка, і її було дуже важко знайти.

У auth.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"
/>

що спричинило цю помилку. Сподіваюся, це комусь допомагає!


2

У моєму випадку це були дозволи у файлі маніфесту, який я мав

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

це було все шапки, коли я змінив його на

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

проблема зникла


1

Крім того,

Перевірте, чи не ставитесь ви до AccountType занадто сильно, як до звичайної старої String.

У мене більша частина коду упакована під com.mycompany.android

Я з успіхом використовую наступний тип AccountType: com.mycompany.android.ACCOUNT .

Зараз у мене є бажання використовувати кілька облікових записів, і коли я намагаюся підходити до додавання ".subType" до кінця свого облікового запису, це не вдається з

uid xxxxx абонента відрізняється від uid автентифікатора

Однак, якщо я використовую "_subType" (підкреслення замість крапки), це справно працює.

Я припускаю, що десь під капотом Android намагається розглядати com.mycompany.android.ACCOUNT як легальну назву пакета, що, безумовно, не є.

Отже, ще раз:

BAD com.mycompany.android.ACCOUNT.subType

ДОБРИЙ com.mycompany.android.ACCOUNT_subType


1

Якщо ви отримуєте цю помилку, і всі вищезазначені рішення не працюють для вас. Крім того, ви припускаєте, що дотримувались усієї процедури. Може існувати ймовірність того, що Службу автентифікації розробив інший розробник, якого ви хочете використовувати для додавання облікових записів.

Що ви можете спробувати, це спробувати підписати свою заявку за допомогою випускного магазину ключів. Тепер ви запускаєте програму. Я гадаю, це має спрацювати для вас.


1

Ось ще одне можливе рішення.

У мене сталася ця помилка, коли мій користувач був зареєстрований у моєму додатку з тим самим електронним адресом, що і його акаунт 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;
}

Ви можете accountManager.getAccountsByType("myservice.com")замість цього зателефонувати .
nickgrim

0

Також переконайтеся, що у вашому 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>


0

Якщо однакові програми з іншого магазину, наприклад, магазин додатків Amazon та магазин Google Play, врешті-решт буде вилучено виняток безпеки, оскільки в цьому випадку підпис програм буде іншим. Якби ви планували використовувати той самий аутентифікатор для цілей одного увійдіть, будь-яка програма не спрацює. я зіткнувся з цією проблемою одного разу. Особливо магазин додатків Amazon підписує свої програми власним підписом з метою безпеки.

Примітка. Якщо тут немає помилки при друкарській помилці або інших відповідей, перевірте підпис програм у разі єдиного входу.


0

Для тих, хто все ще пройшов випуск: https://stackoverflow.com/a/37102317/4171098

У моєму випадку я випадково визначив AuthenticatorService в маніфесті поза <application>тегами. Переміщення декларації всередину <application>вирішило проблему. Надія комусь допоможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.