Google登录服务器实现返回401



当尝试从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!

相关内容

  • 没有找到相关文章

最新更新