【问题标题】:Google Drive API through Google App Engine通过 Google App Engine 的 Google Drive API
【发布时间】:2012-10-02 13:55:47
【问题描述】:

我正在尝试通过 Google App Engine 提供的 App Identity 接口使用 Google Drive API。这基本上允许我的 Web 应用程序与 Google 的 API from server to server 进行通信。

我不需要我的用户登录,我只需要显示我自己的 Google Drive 文档。

但是,在我设置了所有适当的值和范围,并在控制台页面上启用了所有正确的 Google Drive 旋钮后,我仍然可以通过对 https://www.googleapis.com/drive/v2/files 的简单 GET 请求得到这个:

{ "error": { "errors": [ { "domain": "usageLimits", "reason": "dailyLimitExceededUnreg", "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.", "extendedHelp": "https://code.google.com/apis/console" } ], "code": 403, "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." }}

怎么了?我错过了什么?这是实际执行请求的代码 - 有趣的是,如果我使用其他 API(例如 URL 缩短器 API),它会很好地工作:

var scopes = new java.util.ArrayList();                                                                                                    
scopes.add("https://www.googleapis.com/auth/drive");                                                                                       
var appIdentity = AppIdentityServiceFactory.getAppIdentityService();                                                                       
var accessToken = appIdentity.getAccessToken(scopes);

var url = new URL("https://www.googleapis.com/drive/v2/files");                                                                            
var connection = url.openConnection();                                                                                                     
connection.setDoOutput(true);                                                                                                              
connection.setRequestMethod("GET");                                                                                                        
connection.addRequestProperty("Content-Type", "application/json");                                                                         
connection.addRequestProperty("Authorization", "OAuth " + accessToken.getAccessToken());

编辑

例如,如果我只是将 API 更改为使用 urlshortner API,它就可以工作:

var url = new URL("https://www.googleapis.com/urlshortener/v1/url/history");

然后输出:

{ "kind": "urlshortener#urlHistory", "totalItems": 0, "itemsPerPage": 30}

那么肯定有什么东西不能与 Google Drive 和 App Identity 一起使用?

编辑 2

我从这里的正确答案中找到了一些帮助:https://stackoverflow.com/a/12526286/50394

但它谈论的是在 Google Apps 上设置客户端 API 范围,而且我没有使用 Google Apps,我只是使用 Google App Engine 的域foo.appspot.com

【问题讨论】:

  • 这是 Java 吗?与var?您可能希望使用 Google 提供的 OAuth/API 库,这将消除一些用户错误的机会。 code.google.com/p/google-api-java-client
  • Hrm,但这是一个简单的 REST 调用。我不想仅仅为了一个 REST 调用而使用一个完整的库。是的,它仍然是 JVM(Rhino)。但我可以使用相同的 API。
  • addRequestProperty 添加标题而不是查询参数,对吗?也许尝试记录您返回的访问令牌并手动尝试使用该令牌的请求?
  • 您不应该在授权标头中使用“Bearer”而不是 OAuth 吗?
  • @JasonHall 我编辑的问题表明,如果我使用不同的 API(例如 urlshortener),相同的代码也可以工作。

标签: java google-app-engine google-api google-drive-api


【解决方案1】:

您收到的 403 错误意味着您的 GET 中没有 Authorization 标头。逻辑是,如果没有 Authorization 标头,您就是匿名的(您是军团等等 :-))。匿名使用的驱动器配额为零,因此消息。 URL 缩短器具有更高的匿名配额,因此可以正常工作。

我建议您将 URL 更改为指向您自己的 http 服务器,并检查您实际发送的标头。

【讨论】:

  • 我可以使用 API 读取我的 urlshortener 历史记录,所以它不能是匿名的,可以吗?
  • 有没有办法记录正在发送的标头?我周围没有 http 服务器。
  • 您在使用 Development Server 时是否会遇到同样的错误,或者仅在 appspot.com 上会遇到同样的错误?如果您在 Dev 上遇到错误,您可以在 localhost 上设置一个服务器并使用它。您可以这样做的另一种方法是将驱动器 URL 从 https 更改为 http 并使用 Wireshark 捕获流量。我不知道是否支持发送到 http,但这没关系,因为您只对查看您的请求标头感兴趣。
  • 我能够使用同一个 Appengine 服务器记录我的 HTTP 标头。这是输出:Content-Type: application/json Authorization: Bearer xxx Host: xxx.appspot.com User-Agent: AppEngine-Google; (+http://code.google.com/appengine; appid: s~xxx) X-AppEngine-Country: US X-AppEngine-Region: ? X-AppEngine-City: ? X-AppEngine-CityLatLong: 0.000000,0.000000
  • 所以Authorization 标头正在设置中。
【解决方案2】:

AFAICT,您应该在 Authorization 标头中使用 Bearer。

可能发生的情况是,Drive API 无法识别服务帐户(因为标头错误?),因此将其视为匿名请求,因为也没有提供 key 参数(请参阅 common query params) .

试试这个:

connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());

或者您可以尝试将令牌添加为access_token 查询参数。

【讨论】:

  • 嗨,亚历克斯。我尝试将其更改为 Bearer,并直接在 url 中传递了access_token,但我得到了同样的错误。您知道我是否需要在 Api 控制台页面中设置额外的东西吗?我是否也需要启用 Drive SDK?我在网上找不到任何相关信息。
  • 您也可以查看我已编辑的问题。如果我使用不同的 API - 例如 urlshortener,我将展示 API 的工作原理。所以认证部分没问题?
  • 抱歉,我想当然地认为您启用了 Drive API。你没有吗?另外,不要忘记将您的应用添加到 API 控制台上的团队成员列表选项卡中。
  • 请注意,这里有 Drive SDK 和 Drive API。从你的代码来看,我猜你只需要后者。
  • 团队成员是什么意思?我该怎么做呢?团队成员部分我还没碰过。
【解决方案3】:

我认为您至少应该设置一个 API 控制台条目,并在 https://code.google.com/apis/console 启用 Drive API 创建此文件后,您将获得一个可在您的 GoogleCredential 对象中使用的 ID。您可以从 GoogleCredential 对象获取访问令牌,然后将其添加到您的请求中。

【讨论】:

  • 这对你有用吗?我想避免仅仅为了一个简单的 REST 调用而使用一个完整的库。我想知道为什么您不能在 App Engine App Identity API 中设置 serviceAccountId。
  • 我让它与 serviceAccountId 一起使用,但您也可以使用 AppIdentityCredential。我认为这是他们最快的方法。如果您不想使用该库,请确保您阅读此处提供的文档developers.google.com/accounts/docs/OAuth2 并创建您自己的实现。我怀疑它是否会更有效(至少不是时间明智)
  • @StefanHogendoorn 您是否必须在 API 控制台中进行任何设置才能使其正常工作?我启用了 Drive API。我认为这是我在权限方面必须做的额外事情?
  • 内部 App Engine API 应该为我处理所有这些,这就是我一直在线阅读的内容。所以我在权限方面一定缺少一些东西——比如我需要以某种方式授予对我的服务帐户的访问权限。
【解决方案4】:

我在此处 (Google drive via service accounts) 看到的是,您使用的样式略有不同,该样式使用从开发者控制台检索到的 API KEY。
对我来说相关的部分是生成一个“服务器应用程序的密钥”,然后使用我没有在其他任何地方阅读过的这种技术!

      HttpTransport httpTransport = new NetHttpTransport();
  JsonFactory jsonFactory = new JacksonFactory();
  AppIdentityCredential credential =
      new AppIdentityCredential.Builder(DriveScopes.DRIVE).build();
  // API_KEY is from the Google Console as a server API key
  GoogleClientRequestInitializer keyInitializer =
      new CommonGoogleClientRequestInitializer(API_KEY);
  Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential)
      .setGoogleClientRequestInitializer(keyInitializer)
      .build();

【讨论】:

    【解决方案5】:

    这个answer 声称:

    Drive SDK 不支持服务帐户,因为它的 安全模型。

    如果仍然如此,一种解决方法是使用常规 Google 帐户执行一次常规 OAuth 舞蹈,并将访问和刷新令牌持久保存在数据存储区中。

    【讨论】:

    • 是的,我可以使用常规的 OAuth 库。但我想了解为什么 App Identity 不能与 Drive API 一起使用。不会是bug吧?
    • Luca,我相信这个视频一定能帮你解决问题:youtube.com/watch?v=iK14bfd6qhs
    猜你喜欢
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多