如何使用Google Picker通过"drive.file"范围访问文件?

13

我的基于Google Drive的Web应用程序可以使用drive权限范围正常工作,但是除非必要,否则这样使用广泛的范围是不好的实践。我想将范围限制为drive.file,以便只能访问由应用程序创建和使用Google Picker打开的文件,但我无法使其正常工作。

由应用程序创建的文件可以正常打开。然而,使用Google Picker打开的文件无法访问;尝试下载此类文件会导致404错误。当我在Google Drive中右键单击文件并选择“查看授权应用程序”时,我的应用程序未列为已授权应用程序之一。

如果将范围扩展到drive,代码将正常工作。

我编写了一个最小化测试页面,该页面应下载用户在Google Picker中选择的文件。可以通过调用auth(),然后是showPicker()来启动该进程。代码的关键部分如下:

gapi.auth.authorize({
    client_id: '123456789012.apps.googleusercontent.com',
    scope: 'https://www.googleapis.com/auth/drive.file',
    immediate: false
});

...

var picker = new google.picker.PickerBuilder()
    .setAppId('123456789012')
    .addView(new google.picker.DocsView(google.picker.ViewId.DOCS_IMAGES))
    .setOAuthToken(gapi.auth.getToken().access_token)
    .setCallback(onPickerAction)
    .build();
picker.setVisible(true);

...

function onPickerAction(data) {
    if ( data.action === google.picker.Action.PICKED ) {
        var id = data.docs[0].id;
        var request = new XMLHttpRequest();
        request.open('GET', 'https://www.googleapis.com/drive/v2/files/' + id);
        request.setRequestHeader('Authorization', 'Bearer ' + gapi.auth.getToken().access_token);

        request.addEventListener('load', function() {
            var item = JSON.parse(request.responseText);
            console.log(item);
        });

        request.send();
    }
}

相关问题的结论是应用程序ID设置不正确。这似乎并不影响我;我已经测试了我能想到的所有组合,但没有任何运气。


如果这么简单,我在文档中很幸运。查看:https://developers.google.com/picker/docs/index#gdata,似乎`scope`设置为数组,而不是平面字符串,例如:`scope: ['https://www.googleapis.com/auth/photos']`。如果您将其更改为:`scope: ['https://www.googleapis.com/auth/drive.file']`,您的代码是否有效? - Anthony
另外,我不是完全清楚作用域的工作原理,但我看到 drive.file 范围列在 Google Drive 范围中,但它没有列在 Google Picker 范围子集中: https://developers.google.com/picker/docs/index#otherviews。这个问题可能仅仅是因为 drive.file 不是 pickerBuilder() 的可用范围吗? 试图从控制台进行黑客攻击,gapi.auth.getToken() 返回 null,导致 showPicker() 失败。 但这可能是其他原因... - Anthony
好的,所以从控制台失败是因为auth()使用了一个弹出窗口,需要解除阻止。授权后,我使用showPicker()得到以下结果:无法将消息发布到https://docs.google.com。接收者的来源为http://rpg-ambience.com。在加载'https://docs.google.com/picker?<blah>'时遇到无效的'X-Frame-Options'头文件:'ALLOW-FROM http://rpg-ambience.com'不是一个被认可的指令。该头文件将被忽略。但是选择器确实加载了,并且没有下载,但控制台记录了文件对象详细信息,因此尝试使用scope:['blah'] - Anthony
你曾经成功地使用 "drive.file" 范围与 picker 进行配合工作吗? - pinoyyid
1
@pinoyyid:目前为止还没有运气。我考虑开始悬赏,但我不确定它是否有帮助,因为这是如此特定于API。在官方的Google Drive开发者社区发布也没有得到任何解决方案:https://plus.google.com/108061244596087600297/posts/YcdzVtnXkta - Jakob
@pinoyyid:在Google+的对话中得到了新的建议,问题现在已经解决,我把解决方案添加为答案在这里。 - Jakob
3个回答

6
OP的答案中提到的Google+ Plus对话给了我关键信息。要使它工作,必须正确配置以下几个方面:
  1. 您的开发人员帐户已启用Drive API和Drive SDK。
  2. 在选择器上设置的appId必须与clientId的第一部分匹配,例如:('1932384883-qI99fef9f9ghh9n99vvsqa9zxczx8cz8xcc.googleusercontent.com'中的'1932384883')
  3. 在Drive SDK配置中,定义一个打开URL。 URL不必完全匹配打开选择器的URL,但源(例如https://domain.com)必须匹配。
  4. 在“Web应用程序的客户端ID”部分中,上述打开URL还必须包含在重定向URI列表中。 源必须包含在javascript源列表中。
  5. 您可能还需要要求用户将您的应用程序“安装”到Google Drive中,或者请求'drive.install'范围以及'drive.file'
这些内容的子集可能有效,但这就是我需要设置的内容,以便简单REST请求的选定文件能够返回200而不是404。

Drive SDK已不再提供支持,已被合并到Drive API中,但“打开URL设置”仍然存在且需要进行设置,您还需要添加一个图标以保存“打开URL设置”。“打开URL设置”位于Drive API设置的第三个选项卡中。 - Benjamin Atkin
4
调用.setAppId()对我来说非常重要,这让我能够在与开放URL不同的域上正常工作。 - Femi
@Femi,我无法为您的评论点赞,但setAppId对我也很关键。 - Elliott Darfink

1

Google+对话中首次建议的那样,问题可以通过以下方式解决:

  1. 确保在Google开发者控制台中启用了Drive SDK(Drive API是另一回事,仅启用该项不足)。
  2. 为您的应用程序指定“打开URL”。

@bamnet:很遗憾我还没有尝试过那个。你有遇到问题吗? - Jakob
Drive SDK不再存在,已被整合到Drive API中,但“打开URL设置”仍然存在并需要进行设置,您还需要添加一个图标以保存“打开URL设置”。它位于Drive API设置的第三个选项卡中。 - Benjamin Atkin

0
除了设置应用程序ID之外,还要确保您在API控制台中的JavaScript起源列表中列出了选择器所在的页面。文件被授权时,应用程序ID和起源都需要匹配。

对于这个测试页面,我已经提供了应用程序ID作为一串数字的字符串(我的客户端ID没有.apps.googleusercontent.com),并且我的API控制台中的来源是http://rpg-ambience.com。对于这种情况,这样做是否正确? - Jakob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接