首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果帐户验证器中的auth令牌过期,请使用刷新令牌。

如果帐户验证器中的auth令牌过期,请使用刷新令牌。
EN

Stack Overflow用户
提问于 2015-12-30 11:18:07
回答 1查看 8.8K关注 0票数 13

我有一个应用程序,它使用AccountManager存储用户的帐户。用户使用OAuth2.0密码-用户名凭据流登录并通过我的REST注册。

用户接收的访问令牌在2小时内到期,需要刷新直到再次过期,以此类推。

我需要在我的身份验证器中实现这个刷新功能。

我有一个名为AccessToken的模型,它有以下字段:

String accessToken, String tokenType, Long expiresIn, String refreshToken, String scope, Long createdAt

因此,目前,在我的getAuthToken方法中,在AccountAuthenticator类中,我接收了这个AccessToken对象,并将它的accessToken字段用作帐户管理器的Auth Token

我需要的是使用我的帐户管理器以某种方式存储刷新令牌和auth令牌,当应用程序试图访问API并获得错误响应:{"error": "access token expired"}时,使用来自先前接收到的refreshToken对象的refreshToken字符串刷新当前访问令牌。不过,我不知道该怎么做。

我在身份验证器类中的getAuthToken方法当前如下所示:

代码语言:javascript
复制
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account,
                           String authTokenType, Bundle options) throws NetworkErrorException {
    if (!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY) &&
            !authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS)) {
        final Bundle result = new Bundle();
        result.putString(AccountManager.KEY_ERROR_MESSAGE, "Invalid authTokenType");
        return result;
    }

    final AccountManager manager = AccountManager.get(context.getApplicationContext());

    String authToken = manager.peekAuthToken(account, authTokenType);

    Log.d("Discounty", TAG + " > peekAuthToken returned - " + authToken);

    if (TextUtils.isEmpty(authToken)) {
        final String password = manager.getPassword(account);
        if (password != null) {
            try {
                authToken = discountyService.getAccessToken(DiscountyService.ACCESS_GRANT_TYPE,
                        account.name, password).toBlocking().first().getAccessToken();
// =======
// Here the above discountyService.getAccessToken(...) call returns
// AccessToken object on which I call the .getAccessToken() 
// getter which returns a string.
// =======
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    if (!TextUtils.isEmpty(authToken)) {
        final Bundle result = new Bundle();
        result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
        result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
        result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
        return result;
    }

    final Intent intent = new Intent(context, LoginActivity.class);
    intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, accountAuthenticatorResponse);
    intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, account.type);
    intent.putExtra(LoginActivity.ARG_AUTH_TYPE, authTokenType);
    final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
    return bundle;
}

AccountGeneral只包含一些常量:

代码语言:javascript
复制
public class AccountGeneral {

    public static final String ACCOUNT_TYPE = "com.discounty";

    public static final String ACCOUNT_NAME = "Discounty";

    public static final String AUTHTOKEN_TYPE_READ_ONLY = "Read only";

    public static final String AUTHTOKE_TYPE_READ_ONLY_LABEL = "Read only access to a Discounty account";

    public static final String AUTHTOKEN_TYPE_FULL_ACCESS = "Full access";

    public static final String AUTHTOKEN_TYPE_FULL_ACCESS_LABEL = "Full access to a Discounty account";
}

该应用程序还将使用SyncAdapter,并将非常频繁地与API交互以同步来自服务器和服务器的数据,这些API调用还需要使用访问令牌作为请求中的参数,因此我确实需要实现这一刷新功能并使其自动化。

有人知道如何正确地实现这一点吗?

PS:我将使用一个本地数据库来存储我的所有数据,我也可以存储令牌对象。虽然不安全,但这似乎是一次简单的黑客攻击。也许我应该每次只存储一个刷新令牌作为db记录,并在应用程序接收到新令牌时更新它?

PPS:我可以自由地改变API的工作方式,所以如果有关于通过使API更好来改进移动应用程序的建议,他们也是非常感谢的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-30 11:57:53

第一次添加帐户时,可以使用以下方法将刷新令牌保存到帐户的用户数据中:

代码语言:javascript
复制
Bundle userdata = new Bundle;
userdata.putString("refreshToken", refreshToken);
mAccountManager.addAccountExplicitly (account, password, userdata);

您还可以在添加帐户后通过调用:

代码语言:javascript
复制
mAccountManager.setUserData(account, "refreshToken", refreshToken);

当访问令牌过期时,可以通过以下方式检索刷新令牌:

代码语言:javascript
复制
String refreshToken = mAccountManager.getUserData(account, "refreshToken");

使用refreshToken检索新的访问令牌。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34528472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档