我正在使用 Google+ 进行身份验证,参考以下链接: https://developers.google.com/+/mobile/android/sign-in
这个过程中大部分看起来没问题。但我遇到的问题是,我们需要获取“一次性授权码”,以便我们的后端服务器可以代表用户执行某些请求,并得到他们的允许。这在“启用应用的服务器端 API 访问”一节中有介绍。然而,由于种种原因,即使授权码有效(例如,该用户还没有对应于我们服务器上的 Google+ 帐号的帐户,这种情况下他们可以创建一个), 我们的服务器也会导致登录失败。
如果发生这种情况,我们可能需要在稍后再次要求用户登录。但我发现,当我用 Google+ 执行第二次登录时,它会给我相同的授权码,即使它已经被我们的服务器使用过了。我尝试了断开和重新连接 Google 客户端 API,并调用 GoogleApiClient.clearDefaultAccountAndReconnect(),但无论我做什么,似乎都会得到相同的授权码。当服务器尝试使用它时,这当然会被拒绝,因为它已经被使用过了。
我想知道我在这里做错了什么。我有以下方法,在初始身份验证过程中调用,如果从我们的服务器检测到响应状态为500(表示之前的调用失败,可能是因为代码已经被使用),则再次调用此方法。
如果发生这种情况,我们可能需要在稍后再次要求用户登录。但我发现,当我用 Google+ 执行第二次登录时,它会给我相同的授权码,即使它已经被我们的服务器使用过了。我尝试了断开和重新连接 Google 客户端 API,并调用 GoogleApiClient.clearDefaultAccountAndReconnect(),但无论我做什么,似乎都会得到相同的授权码。当服务器尝试使用它时,这当然会被拒绝,因为它已经被使用过了。
我想知道我在这里做错了什么。我有以下方法,在初始身份验证过程中调用,如果从我们的服务器检测到响应状态为500(表示之前的调用失败,可能是因为代码已经被使用),则再次调用此方法。
private void dispatchGooglePlusAuthCodeAcquisition() {
AsyncTask<Void, Void, String> authAcquisition = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
Bundle authPreferences = new Bundle();
mUserPermissionNeededForAuthCode = false;
authPreferences.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
"");
String scopesString = Scopes.PROFILE;
WhenIWorkApplication app = (WhenIWorkApplication)WhenIWorkApplication.getInstance();
String serverClientID = app.getGoogleOAuthClientIDForPersonalServer();
String scope = "oauth2:server:client_id:" + serverClientID + ":api_scope:" + scopesString;
String code = null;
authPreferences.putBoolean(GoogleAuthUtil.KEY_SUPPRESS_PROGRESS_SCREEN, true);
try {
code = GoogleAuthUtil.getToken(
mActivity,
Plus.AccountApi.getAccountName(mGoogleApiClient),
scope,
authPreferences
);
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
Log.d(LOGTAG, "Encountered an IOException while trying to login to Google+."
+ " We'll need to try again at a later time.");
} catch (UserRecoverableAuthException e) {
mUserPermissionNeededForAuthCode = true;
// Requesting an authorization code will always throw
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
// because the user must consent to offline access to their data. After
// consent is granted control is returned to your activity in onActivityResult
// and the second call to GoogleAuthUtil.getToken will succeed.
if (!mGooglePlusPermissionActivityStarted) {
mGooglePlusPermissionActivityStarted = true;
mActivity.startActivityForResult(e.getIntent(), RESULT_CODE_AUTH_CODE);
}
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
Log.e(LOGTAG, "Unable to authenticate to Google+. Call will likely never"
+ " succeed, so bailing.", authEx);
}
return code;
}
@Override
protected void onPostExecute(String aResult) {
if (aResult != null) {
// We retrieved an authorization code successfully.
if (mAPIAccessListener != null) {
mAPIAccessListener.onAuthorizationCodeGranted(aResult);
}
} else if (!mUserPermissionNeededForAuthCode) {
// If this is the case, then we didn't get authorization from the user, or something
// else happened.
if (mAPIAccessListener != null) {
mAPIAccessListener.onAuthorizationFailed();
}
Log.d(LOGTAG, "Unable to login because authorization code retrieved was null");
}
}
};
authAcquisition.execute();
GooglePlusAuthUtil
的类,并将授权令牌存储为成员变量。如果授权令牌不为空(也就是说,我已经看到过一次令牌通过网络传输),我会调用clearToken()
方法,然后再次调用getToken()
方法并将结果存储在成员变量中。这确实为我重新生成了令牌。 - jwir3clearToken()
方法调用时发送令牌。你是否尝试在clearToken()
方法完成之前(即以异步方式)调用getToken()
? - jwir3