17

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

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

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

4

5 回答 5

12

我将 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 进行刷新,您将永远无法脱身。
于 2013-08-24T03:58:37.217 回答
1
  1. 您可能希望在 Android 中使用AccountManager API进行身份验证和授权。您可以在此处关注博客。
  2. 对于 OAuth 2.0 服务器端实现,您可以在此处阅读 IETF 草案 V2-31 。
  3. 为了更好地理解 OAuth 2.0,您可以在此处阅读Nitesh Kumar 的博客。
  4. 对于 OAuth 2.0 的服务器端实现,您可以在 Github上 fork Apis 授权服务器repo。
  5. 更多实现选项可以在此处的 OAuth 2.0 网站上找到。
于 2013-07-10T19:30:05.753 回答
1

你看到这篇博文了吗?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;
    }
于 2015-01-04T13:22:08.537 回答
0

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

@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;
}

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

于 2019-09-17T14:09:59.520 回答
-2

getToken()失败的。状态BAD_AUTHENTICATION错误

我也面临同样的问题。

解决方法:检查设备是否用你的谷歌账号登录。

于 2018-02-14T14:57:33.647 回答