Google Books API身份验证错误

时间:2016-01-06 16:24:50

标签: android google-play-services google-books

我正在构建Android应用,并且正在尝试将Google Books API集成到我的应用中。 现在,登录工作。我收到了同意屏幕,其中包含访问我帐户中的Google图书数据的请求。 我现在正尝试使用以下代码从我的库中获取所有书架:

public class GetUsernameTask extends AsyncTask<String, Void, Void> {
    Activity mActivity;
    String mScope;
    String mEmail;

    public GetUsernameTask(Activity activity, String name, String scope) {
        this.mActivity = activity;
        this.mScope = scope;
        this.mEmail = name;
    }

    /**
     * Executes the asynchronous job. This runs when you call execute()
     * on the AsyncTask instance.
     */
    @Override
    protected Void doInBackground(String... params) {
        try {
            String token = fetchToken();
            if (token != null) {
                Log.i("TAG", "Got a token: " + token);
                // Use the token to access the user's Google data.
                String api_key = params[0];
                URL object = new URL("https://www.googleapis.com/books/v1/mylibrary/bookshelves?key=" + api_key);
                HttpsURLConnection connection = (HttpsURLConnection) object.openConnection();
                connection.setRequestProperty("Authorization", token);
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                Log.i("TAG", connection.getResponseMessage());
                InputStream is = connection.getErrorStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = reader.readLine()) != null) {
                    Log.i("TAG", line);
                }
            }
        } catch (IOException e) {
            Log.e("TAG", "Got an exception", e);
        }
        return null;
    }

    /**
     * Gets an authentication token from Google and handles any
     * GoogleAuthException that may occur.
     */
    protected String fetchToken() throws IOException {
        try {
            return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
        } catch (UserRecoverableAuthException userRecoverableException) {
            // GooglePlayServices.apk is either old, disabled, or not present
            // so we need to show the user some UI in the activity to recover.

            Log.i("TAG", "Nu! more exceptions", userRecoverableException);
        } catch (GoogleAuthException fatalException) {
            // Some other type of unrecoverable exception has occurred.
            // Report and log the error as appropriate for your app.
            Log.i("TAG", "Nu! more exceptions", fatalException);
        }
        return null;
    }
}

此代码来自Google文档(https://developers.google.com/android/guides/http-auth)。

作为请求,我附加了“?key = api_key”,由文档(https://developers.google.com/books/docs/v1/using?hl=en#WorkingMyBookshelves)指定,我也在标题中指定了我的令牌。打印令牌时,它看起来像这样:xxxx.YQJ8nJimB8eeQOIdVkkg2WfkobsBkARzc2TWJL4d_2ipIQuJ4U9uFTvNNhye7i0474TbsA

我得到的回报令人惊讶;这是一个401 HTTP错误,即以下内容:

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

作为API密钥,我尝试使用以下内容:

我还发现我的硬盘上有两个debug.keystore文件,一个在C:\ Android \中,另一个在〜\ .android中。我只是决定将两个SHA-1哈希值添加到两个Android密钥(以及OAuth 2.0客户端ID),希望它以某种方式使用其他密钥库 - 无济于事。

我做错了什么?

我也尝试过使用Google Play服务库。这会产生不同的错误;但仍然存在错误。

我使用此代码(在doInBackground方法中)尝试使用所述API:

try {
    Books service = new Books.Builder(AndroidHttp.newCompatibleTransport(), JacksonFactory.getDefaultInstance(), null).setGoogleClientRequestInitializer(new BooksRequestInitializer(api_key)).build();
    List<Bookshelf> shelves = service.mylibrary().bookshelves().list().execute().getItems();
}catch (Exception ex){
    Log.e("TAG", "Error while using Books", ex);
}

使用Android密钥,我收到403 Forbidden HTTP响应,并显示消息“您的API密钥上配置了每IP或每个Referer限制,并且请求与这些限制不匹配。请使用Google Developers如果允许来自此IP或引用者的请求,则更新API密钥配置的控制台。“但是,我没有看到使用Android API密钥的任何IP限制。

使用服务器密钥,我收到400 Bad Request,可能是因为该令牌丢失了。

我做错了什么?我错过了什么?

1 个答案:

答案 0 :(得分:1)

在询问了一些与我关系密切的人之后,我注意到了我设置Authorization标头的方式。根据Wiki(https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side),令牌前面有一个&#34; Type&#34;。对于Google OAuth2,此类型为Bearer

因此,改变

connection.setRequestProperty("Authorization", token);

进入

connection.setRequestProperty("Authorization", "Bearer " + token);

做了这个伎俩。编辑:显然,这是在这里指定的:https://developers.google.com/books/docs/v1/using?hl=en#query-params - 一直在页面底部的标题下,我觉得不适合这么重要的事情。

对于Google API,我现在意识到我没有在任何地方指定令牌。搜索了一下之后,我发现你可以像这样设置Oauth标记:

List<Bookshelf> shelves = service.mylibrary().bookshelves().list().setOauthToken(token).execute().getItems();

这给了我想要的结果。请注意:这是使用服务器键完成的,而不是Android键。 Android密钥仍然给我403 ipRefererBlocked错误。