【问题标题】:Google plus for android: Invalid Credentials适用于 android 的 Google plus:凭据无效
【发布时间】:2013-02-19 10:13:33
【问题描述】:

我正在使用以下代码获取访问令牌,在连接到 Google+ 后,以获取个人资料信息和电子邮件:

String sAccessToken = GoogleAuthUtil.getToken(this,mPlusClient.getAccountName() + "",
                          "oauth2:" + Scopes.PLUS_PROFILE + " 
                          https://www.googleapis.com/auth/userinfo.profile 
                          https://www.googleapis.com/auth/userinfo.email");

我不会存储并尝试重复使用此访问令牌。相反,我每次都要求一个访问令牌,期待一个新的(不同的)令牌,这样我就不需要检查它是否过期等等。

但我每次请求时都会获得相同的访问令牌。我卸载了该应用程序,清除了 Google+ 应用程序 的数据,但仍然获得相同的访问令牌。

实际问题是,使用此访问令牌会产生 401 错误 - "message": "Invalid Credentials"

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "authError",
    "message": "Invalid Credentials",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Invalid Credentials"
 }
}

这是浏览器的响应。

在设备上,我在 Logcat 中得到了这个:

02-25 02:09:46.919: W/System.err(3022): java.io.FileNotFoundException: https://www.googleapis.com/oauth2/v1/userinfo
02-25 02:09:46.929: W/System.err(3022):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:521)
02-25 02:09:46.929: W/System.err(3022):     at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:258)
02-25 02:09:46.929: W/System.err(3022):     at com.example.gmaillogin.MainActivity$connectAsyncTask.doInBackground(MainActivity.java:269)
02-25 02:09:46.929: W/System.err(3022):     at com.example.gmaillogin.MainActivity$connectAsyncTask.doInBackground(MainActivity.java:1)
02-25 02:09:46.929: W/System.err(3022):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-25 02:09:46.929: W/System.err(3022):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
02-25 02:09:46.929: W/System.err(3022):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
02-25 02:09:46.929: W/System.err(3022):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
02-25 02:09:46.929: W/System.err(3022):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
02-25 02:09:46.929: W/System.err(3022):     at java.lang.Thread.run(Thread.java:1019)

第 269 行:

urlConnection = (HttpURLConnection) url.openConnection();

完整代码:

URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo");
String sAccessToken = GoogleAuthUtil.getToken(
                        MainActivity.this,
                        mPlusClient.getAccountName() + "",
                        "oauth2:" + Scopes.PLUS_PROFILE + " 
                                            https://www.googleapis.com/auth/userinfo.profile 
                                            https://www.googleapis.com/auth/userinfo.email");

            Log.d("sAccessToken = ", "" + sAccessToken);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestProperty("Authorization", "Bearer "
                    + sAccessToken);

            BufferedReader r = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream(), "UTF-8"));
            StringBuilder total = new StringBuilder();
            String line;
            while ((line = r.readLine()) != null) {
                total.append(line);
            }
            line = total.toString();

编辑:

这肯定是因为访问令牌已过期。这是意料之中的,但我想我每次打电话都会得到一个新的访问令牌。

但正如here所说:

如果 android 设备已经有一个身份验证令牌(对于特定的 您尝试访问的 GData 服务),它将返回给您

所以,我必须这样做:

if (server indicates token is invalid) {
              // invalidate the token that we found is bad so that GoogleAuthUtil won't
              // return it next time (it may have cached it)
              GoogleAuthUtil.invalidateToken(Context, String)(context, token);
              // consider retrying getAndUseTokenBlocking() once more
              return;
          }

docs这样说

但是如何检查访问令牌是否过期或无效?

通过捕获异常 - 是唯一的解决方案吗?

实际上 Exception 是 java.io.FileNotFoundException 这没有意义。

【问题讨论】:

  • 您是否有理由尝试手动执行此操作,而不是使用 PlusClient 上提供的方法?客户端应自动代表您的应用处理令牌交换。
  • 我关注this 获取访问令牌。自动处理它的另一种方式是什么?

标签: android google-plus access-token


【解决方案1】:

在此涵盖基础:您是否通过指定您的应用程序包名称和证书(测试或产品)的 SHA-1 指纹来为您的 Android 应用程序 register a Google APIs Console project 并创建 OAuth 2.0 客户端 ID?

401 无效凭据消息通常是由于 API 控制台项目未配置或其中一项设置无效。

专门针对 Google+ SDK 的设置过程的步骤如下:https://developers.google.com/+/mobile/android/getting-started

编辑

PlusClient 可以自动为您处理令牌。我建议使用PlusClient 提供的方法并允许客户端管理令牌而不是手动进行。如果您需要通过PlusClient 获取电子邮件或个人资料数据,请参阅PlusClient.loadPerson() 和电子邮件PlusClient.getAccountName(),更多详细信息请访问https://developers.google.com/+/mobile/android/people

【讨论】:

  • 是的,我做了你在答案中提到的所有事情。经过一番研究,我发现这绝对是因为Access Token有没有办法检查访问令牌是否过期或有效?
  • 请参阅快速入门示例,了解有关如何验证/验证令牌的一些代码,以便它们不仅有效,而且对给定的用户和应用程序也有效。从第 140 行开始可以看到 Java 服务器端应用验证:github.com/googleplus/gplus-quickstart-java/blob/master/src/com/…
  • 嘿@BrettJ,这曾经对我有用,但就在几天前它停止工作,现在它抛出这个错误 com.google.android.gms.auth.GoogleAuthException: Unknown。知道为什么吗?我的瞄准镜有问题吗? gist.github.com/lawloretienne/7351151
  • 您最近升级了您的 SDK 和 Google Play 服务吗?
【解决方案2】:

我遇到了类似的问题。为了解决访问令牌过期的问题,我在客户端解码令牌,并检查令牌有效负载中的“exp”字段。这样,我可以在发送到服务器之前识别令牌过期。 更多详情请参阅blog post

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多