This nice tutorial是Android上帐户身份验证的一个非常好的介绍,并通过使用Android的AccountManager
来实现。
但是,我需要使用Bearer令牌为OAuth2 API创建客户端应用程序以进行身份验证。在获得令牌时,我收到了它的到期时间戳,但我不清楚存储的位置以及如何正确使用它。 问题是,如果我不想不必要地去服务器,应用程序会意识到,只有在请求任何随机资源时从服务器收到HTTP 401错误后,承载才会变为无效。那么,解决这个问题的最佳做法是什么:
invalidateAuthToken
并重试。 由于我是Android开发的新手,我希望解决方案也可能与我预期的完全不同。
如果相关,我打算使用Volley进行服务器通信。
答案 0 :(得分:9)
是的,调用AccountManager#invalidateAuthToken
会删除上次保存的身份验证令牌(OAuth2案例中的访问令牌),并希望您在下一次AccountAuthenticator#getAuthToken
呼叫时检测到该令牌。例如,以下是该方法的代码:
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
// Extract the username and password from the Account Manager, and ask
// for an appropriate AuthToken.
final AccountManager am = AccountManager.get(mContext);
String authToken = am.peekAuthToken(account, authTokenType);
// EXTRA: I am also storing the OAuth2 refresh token in the AccountManager
Map<String, String> refreshResult = null;
String refreshToken = am.getUserData(account, KEY_REFRESH_TOKEN);
if (TextUtils.isEmpty(authToken) && !TextUtils.isEmpty(refreshToken)) {
// lets try to refresh the token
// EXTRA: AuthenticationProvider is my class for accessing the authentication server, getting new access and refresh token based on the existing refresh token
refreshResult = AuthenticationProvider.
refreshAccessToken(am.getUserData(account, KEY_REFRESH_TOKEN));
}
// If we get a result from the refresh - we return it
if (!refreshResult.isEmpty()) {
authToken = refreshResult.get(AccountManager.KEY_AUTHTOKEN);
// EXTRA: new refresh token used only in OAuth2
refreshToken = refreshResult.get(KEY_REFRESH_TOKEN);
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
// store the new tokens in the system
am.setAuthToken(account, authTokenType, authToken);
am.setUserData(account, KEY_REFRESH_TOKEN, refreshToken);
result.putString(AccountManager.KEY_AUTHTOKEN, refreshResult.get(AccountManager.KEY_AUTHTOKEN));
result.putString(KEY_REFRESH_TOKEN, refreshResult.get(KEY_REFRESH_TOKEN));
return result;
}
// If we get here, then we couldn't access the user's password - so we
// need to re-prompt them for their credentials. We do that by creating
// an intent to display our AuthenticatorActivity.
final Intent intent = new Intent(mContext, LoginActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
我还收到了问题中提到的confirmation from the author of the blog post。
SyncAdapter
无法直接帮助,因为它们的真正目的是异步(对于开发人员)和透明地(对于用户)从网络获取数据。他们只需使用AbstractAccountAuthenticator
并在适当的地方调用其方法。
答案 1 :(得分:1)
之前我遇到了同样的问题,并在Android中将此library转换为handel OAuth2。但该库是Retrofit的扩展,它简化了对OAuth 2提供程序进行身份验证的过程,但您仍然可以使用它。