【问题标题】:Token authentication with Volley使用 Volley 进行令牌认证
【发布时间】:2013-07-01 08:42:13
【问题描述】:

如果我有一个使用用户名/密码进行身份验证并为后续请求获取身份验证令牌的服务器,那么解决此问题的最佳方法是什么?

流程应该是这样的: - 开始请求 - 如果我们没有身份验证令牌 - 使用用户名和密码获取它 - 使用身份验证令牌发出请求 - 如果请求因令牌过期而失败,则使用用户名和密码获取新的身份验证令牌 - 使用新的身份验证令牌重试请求 - 完成

我注意到 Volley 可能已经有一些可以解决这个问题的东西 - Authenticator https://android.googlesource.com/platform/frameworks/support/+/4474bc11f64b2b274ca6db5a1e23e8c1d143d5fa/volley/src/com/android/volley/toolbox/Authenticator.java 它包含 getAuthToken() 和 invalidateAuthToken() 方法,这正是我想要的。但是好像根本没在图书馆里用过。

【问题讨论】:

  • 我刚刚检查了来源,看起来你是 - 代码中没有使用验证器。所以可能你必须手动完成。
  • 是的。与此同时,我复制了 BasicNetwork 类并在那里进行了调整,以便为我进行身份验证。
  • 你能把你的做法作为答案吗

标签: android android-volley


【解决方案1】:

我将 volley 用于使用 longlive (LLT) 和 shortlive (SLT) 令牌的身份验证系统。

我是手动完成的,但一旦你把它全部布置好,它就真的没什么工作了。

让所有安全请求子类化一个 baseSecureRequest,它可以在其 onResponse() 和 onErrorResponse() 中处理所有安全请求共有的这种令牌机制。

它变成了一点 node.js 风格,请求发送其他请求并等待回调。


一个应用程序可能有十几个屏幕,其中只有一半需要授权访问 - 所以每个屏幕都应该不知道其请求的要求。

场景 A

  • 我们尝试发送安全请求。我们注意到我们没有 SLT 内存,所以做一个 TokenRequest。
  • TokenRequest 的 onResponse() 保存 该令牌到内存(让单例会话管理器保留它或 类似的无所不在的类)
  • 现在回调到原来的 具体类请求对象以继续使用新更新的令牌。

场景 B

  • 我们发送了一个安全请求,但我们的 SLT 已过时(已过期)

  • 服务器返回一个错误代码或消息,您可以在 您的 baseSecureRequest 的一般 onErrorResponse()。

  • 在这个 onError() 中,您发送一个 refreshTokenRequest() 对象 尝试通过使用 LLT 从服务器请求新的 SLT 来刷新内存中的 SLT。

  • refreshTokenRequest 的 onResponse() 现在可以回调到 重新发送的原始请求。

  • 然而 onErrorResponse() 可能应该放弃整个事情,因为机会是 任何不是连接错误的东西 - 都是由以下原因引起的错误 无效的 LLT。如果您继续尝试使用糟糕的 LLT 进行刷新,您将永远无法脱身。

【讨论】:

  • 我不同意。 onErrorResponse 刷新令牌为时已晚,因为无论您做什么,请求都会被视为失败。请求新令牌的正确位置将在自定义 RetryPolicy 类中。在 2 种情况下会要求重试策略准备重试:1. 超时 2. AuthFailureError - 这是你想要的。
  • 这不是一个有效的解决方案。当 volley 返回错误时,它已经重试了您的请求。执行此操作的正确位置是编写自定义重试策略。假设您的 API 请求有 3 个线程。这意味着从您的网络队列中,理论上您可以并行处理 3 个请求。现在,如果 SLT 过期,您将在不同时间获得 3 次失败。这意味着您将使用旧 SLT 重试大量 refreshTokenRequest 或继续使用新令牌重试,即使您拥有有效令牌。
  • @SaKet 您能否详细解释一下在并行处理请求的多线程情况下如何处理刷新令牌。如果你能分享一个代码 sn-p 那就太好了。
【解决方案2】:
  1. 您可能希望在 Android 中使用AccountManager API 进行身份验证和授权。您可以关注博客here
  2. 对于 OAuth 2.0 服务器端实施,您可以阅读 IETF 草案 V2-31 here
  3. 为了更好地理解 OAuth 2.0,您可以阅读Nitesh Kumarhere 的博客。
  4. 对于 OAuth 2.0 的服务器端实现,您可以在 Github 上 fork Apis Autherization Server repo。
  5. 更多实现选项可以在OAuth 2.0 here的网站上找到。

【讨论】:

  • 感谢您的回复,但我的问题专门针对 Volley。不是如何做授权,而是如何与 Volley 集成
  • AndroidAuthenticator 似乎使用 accountManager,但我不确定我们应该如何使用 AndroidAuthenticator。
【解决方案3】:

您看到这篇博文了吗? https://smaspe.github.io/2013/06/06/volley-part2.html

演示了一种覆盖请求对象以使用 twitter 令牌的简单方法。

@Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<String, String>();
        String auth = "Basic "
                + Base64.encodeToString((TwitterValues.CONSUMER_KEY 
                + ":" + TwitterValues.CONSUMER_SECRET).getBytes(),
                        Base64.NO_WRAP);
        headers.put("Authorization", auth);
        return headers;
    }

【讨论】:

  • 链接关闭。你还有这样的帖子吗?
  • @davidbonachera 链接的博客最近被移动(并重命名)我更新了链接。
【解决方案4】:

就我而言,我将“基本”身份验证更改为令牌身份验证,如下所示:

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String,String> headers = new HashMap<>();
    //todo Esta es una authenticación basica (usuario y contraseña)
    /*String credentials = USER+":"+PASSWORD;
    String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
    headers.put("Authorization", auth);*/
    //todo Esta es una authenticación con token (por tiempos)
    headers.put("Authorization", "Bearer" + " " + "tokenString");//App.getToken()
    return  headers;
}

我所做的是将登录名保存在一个全局静态变量中,然后就可以使用它了。

【讨论】:

    【解决方案5】:

    getToken() 失败。状态BAD_AUTHENTICATION错误

    我也遇到了同样的问题。

    解决方法:检查设备是否使用您的 Google 帐户登录。

    【讨论】:

    • 这应该是一个答案还是一个新问题?
    猜你喜欢
    • 1970-01-01
    • 2011-12-12
    • 2022-09-11
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2017-08-22
    相关资源
    最近更新 更多