当尝试从Play Services 8.1中的Google+Sign-In切换到Play Services 8.3中的新Google Sign-In时,服务器端组件停止工作,并开始在对Google服务器的每个API调用上抛出401。
当Android应用程序使用Google Play Services 8.1时:
构建等级:
compile 'com.google.android.gms:play-services-plus:8.1.0'
安卓客户端:
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.addScope(new Scope("email"))
.build();
String scopes = "oauth2:profile email";
accessToken = GoogleAuthUtil.getToken(
SignInActivity.this,
Plus.AccountApi.getAccountName(mGoogleApiClient),
scopes); // then send accessToken to the server
服务器端:
// get user details from Google+ REST API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plusService = new Plus.Builder(new NetHttpTransport(), new JacksonFactory(), null)
.setApplicationName("AppName")
.setHttpRequestInitializer(credential)
.build();
Person person = plusService.people().get("me").execute();
切换到Google Play Services 8.3时:
构建等级:
compile 'com.google.android.gms:play-services-auth:8.3.0'
Android应用程序:
GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestServerAuthCode("GOOGLE_CLIENT_ID", false)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, googleSignInOptions)
.build();
使用相同的服务器代码,get("me")调用返回:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError"
} ],
"message" : "Invalid Credentials"
}
此外,请注意,使用新的谷歌登录Api,只要在Android客户端上请求基本的配置文件范围,您就可以在服务器上用代码交换令牌时获得ID令牌。如果你想要的只是全名、电子邮件地址和一张照片,那就足够了。
您可以将GoogleSignInAccount.getServerAuthCode()的结果传递给服务器,然后使用以下代码
HttpTransport transport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
try {
// Exchanges the code for tokens.
GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(
transport,
jsonFactory,
// Very important: Explicitly specify this new endpoint.
"https://www.googleapis.com/oauth2/v4/token",
SERVER_CLIENT_ID,
SERVER_CLIENT_SECRET,
serverAuthCodeFromAndroid,
"" /* redirectUri, must be blank with auth code coming from Android */)
.execute();
// Get the id token from the exchange result
// It will be non-null if basic profile scopes are requested
// when requesting the serverAuthCode on (Android) client side.
GoogleIdToken googleIdToken = response.parseIdToken();
// Verify the id token
GoogleIdTokenVerifier verifier =
new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// For some old version of libraries
.setIssuer("https://accounts.google.com")
.setAudience(Arrays.asList(SERVER_CLIENT_ID))
.build();
boolean verified = googleIdToken.verify(verifier);
if (!verified) {
// Spoofing!! This is not a legitimate id token issued by
// Google to your web application!
return;
}
// Get the profile info.
GoogleIdToken.Payload payload = googleIdToken.getPayload();
String userId = payload.getSubject();
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
} catch (GeneralSecurityException | IOException e) {
// error handling
}
不需要Google+API!