我想知道什么是最好的方式来刷新通过OAuth 2.0中的客户端凭据流获得的访问令牌。我已经阅读了规范,但似乎无法找到适合我的特殊情况的答案。
对于我的特定情况,我正在使用适用于Android应用程序的Spotify Web API来搜索内容(曲目,专辑和/或歌手)。为了执行搜索,我需要访问令牌。由于我对Spotify用户的数据不感兴趣,因此我可以使用客户端凭据流来获取访问令牌,这在Spotify的术语here中进行了解释。
由于访问令牌最终可能会过期,因此我必须找出一种在过期后刷新它的方法。我最终想知道的是我的方法是否有效,以及是否对我的方法有任何担忧。
首先,我将访问令牌存储在SharedPreferences
中。在onCreate()
中,我有以下内容:
@Override
protected void onCreate(Bundle savedInstanceState) {
// A bunch of other stuff, views being initialized, etc.
mAccessToken = getAccessToken();
// If the access token is expired, then we will attempt to retrieve a new one
if (accessTokenExpired()) {
retrieveAccessToken();
}
}
我对accessTokenExpired()
和retrieveAccessToken()
的定义如下:
private boolean accessTokenExpired() {
// If mAccessToken hasn't yet been initialized, that means that we need to try to retrieve
// an access token. In this case, we will return true;
if (mAccessToken == null) {
return true;
}
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
long timeSaved = preferences.getLong(PREFERENCES_KEY_TOKEN_RESPONSE_TIME_SAVED, 0L);
long expiration = preferences.getLong(PREFERENCES_KEY_TOKEN_RESPONSE_EXPIRATION, 0L);
long now = System.currentTimeMillis()/1000;
long timePassed = Math.abs(now - timeSaved);
if (timePassed >= expiration) {
return true;
} else {
return false;
}
}
关于retrieveAccessToken()
值得注意的一件事是我在HTTP请求中使用Retrofit
:
private void retrieveAccessToken() {
// First, we obtain an instance of SearchClient through our ClientGenerator class
mClient = ClientGenerator.createClient(SearchClient.class);
// We then obtain the client ID and client secret encoded in Base64.
String encodedString = encodeClientIDAndSecret();
// Finally, we initiate the HTTP request and hope to get the access token as a response
Call<TokenResponse> tokenResponseCall = mClient.getAccessToken(encodedString, "client_credentials");
tokenResponseCall.enqueue(new Callback<TokenResponse>() {
@Override
public void onResponse(Call<TokenResponse> call, Response<TokenResponse> response) {
Log.d(TAG, "on Response: response toString(): " + response.toString());
TokenResponse tokenResponse = null;
if (response.isSuccessful()) {
tokenResponse = response.body();
Log.d(TAG, tokenResponse.toString());
mAccessToken = tokenResponse.getAccessToken();
saveAccessToken(tokenResponse);
}
}
@Override
public void onFailure(Call<TokenResponse> call, Throwable t) {
Log.d(TAG, "onFailure: request toString():" + call.request().toString());
mAccessToken = "";
}
});
}
最后,saveAccessToken(tokenResponse)
是accessTokenExpired()
的补充,在这里我将令牌响应中的值保存到SharedPreferences
中,而不是检索它们。
我对此有任何疑问吗?我从this SO post那里得到了这个想法,并对其做了一些修改。 Spotify不在其访问令牌响应中提供刷新令牌。因此,在这里我不能利用它来减少我发出的访问令牌请求的数量。
对此表示感谢!
答案 0 :(得分:1)
两个注意事项是:
check the token is valid -> make some requests with the token -> repeat
的周期中,您花费了一个多小时使用令牌。您可以执行的另一种方法是计算now + expected_api_request_time > token_expiration_time
,其中expected_api_request_time
是您设置的常数,但是我认为处理令牌到期是一种更好的做法(无论如何,您可能希望能够重试在网络不稳定的情况下。timeSaved
和expiration
时,或者只是计算令牌最初到期的时间并将其保存。这相对较小,我认为这和您完成的方式都很好。