Android OAuth2 Bearer令牌最佳做法

 mobiledu2502854717 发布于 2023-02-09 18:41

这个很好的教程非常好地介绍了Android上的帐户身份验证,并通过使用Android来实现AccountManager.

但是,我需要使用承载令牌为OAuth2 API创建客户端应用程序以进行身份​​验证.在获得令牌时,我收到了它的到期时间戳,但我不清楚存储的位置以及如何正确使用它.问题是,如果我不想不必要地去服务器,应用程序会意识到,只有在请求任何随机资源时从服务器收到HTTP 401错误后,承载才会变为无效.那么,解决这个问题的最佳做法是什么:

    我的代码中的每个网络请求都应该具有重试机制,以防承载令牌在此期间变为无效吗?我可能会invalidateAuthToken在捕获异常时重试.

    可以同步适配器以某种方式帮助吗?

由于我是Android开发的新手,我希望解决方案也可能与我预期的完全不同.

如果它是相关的,我打算使用Volley进行服务器通信.

1 个回答
  • 经过一番调查后我发现了自己的答案:

      是的,调用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;
      }
      

      我还收到了问题中提到的博客文章的作者的确认.

      SyncAdapters无法直接帮助,因为它们的真正目的是异步(对于开发人员)和透明地(对于用户)从网络获取数据.他们只是AbstractAccountAuthenticator在适当的时候使用并调用它的方法.

    2023-02-09 18:42 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有