[android] SecurityException : 호출자 uid XXXX가 인증 자의 uid와 다릅니다.

샘플 동기화 어댑터 애플리케이션을 구현하려고 할 때 위의 예외를 수신했습니다. 이 문제와 관련된 많은 게시물을 보았지만 만족스러운 답변이 없습니다.

그래서 다른 사람이 같은 문제에 빠질 경우를 대비하여 여기에 내 솔루션 을 적어 두겠습니다 .



답변

이와 같은 문제를 디버깅하기위한 다른 유용한 팁.

먼저 일부 태그에 대해 자세한 로깅을 활성화합니다.

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


답변

먼저이 게시물에 설명 된 조건을 확인하십시오 .

[…] 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.


답변

내 경우에는 문제는 단순히 ACCOUNTTYPE의 불일치에 선언 매우이었다 res/xml/authenticator.xmlandroid:accountType="com.foo"하지만, 같은 잘못 참조 "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과 동일한 문자열이어야합니다!

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


답변

내 오류는 AccountManager getAccounts () 메서드가 내 응용 프로그램 컨텍스트와 관련된 계정 만 반환한다고 가정했습니다. 나는 변했다

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

…에

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


답변

매니페스트의 인 텐트 필터에 잘못된 값을 입력하면 동일한 오류가 나타납니다. sync-adapters에 대한 android-dev 자습서를 살펴 보았고 syncadapter / accountauthenticator에 대한 “meta-data / android : name”뿐만 아니라 “intent-filter / action android : name”에 대한 가짜 값을 설정했습니다. 이 실수로 인해 로그에 동일한 오류가 나타납니다.

레코드의 경우 올바른 값은 {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에서