使用登录用户访问共享文档会导致文件未找到错误,但无需身份验证即可使用

Accessing a shared document with a logged in user results in a file not found error, but works with no authentication

我正在使用 https://developers.google.com/drive/v3/reference/files/get to read someone's shared (read-only) document. The document is shared globally, anyone with the link can view the contents. Having the shared url (like https://docs.google.com/document/d/acbcdef0123456789/edit?usp=sharing ),我可以在浏览器中以登录用户和没有任何用户(隐身模式)的方式查看文档。只要不涉及用户,使用 javascript 访问文档就可以。成功登录后(见下文),服务器响应 "File not found" (404) 错误。注销后,我可以再次访问同一个文档。

如果我使用 curl 从命令行发送相同的请求但没有 Authorization: Bearer... header,响应是 200,好的。授权headers,响应为404.

工作代码在这里:http://jsbin.com/hayafubuce/edit?html,js,output

如果我有 valid/logged 用户,我如何访问共享文档???
(无法通过电子邮件发送邀请或与特定用户共享。)

更新: 如果我使用 https://www.googleapis.com/auth/drive 范围而不是 https://www.googleapis.com/auth/drive.file 一切正常。但我不希望我的应用程序能够访问用户的所有文件,只能访问它创建的文件。

加载的 sdks:

<script type="text/javascript" src="https://apis.google.com/js/platform.js"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>

正在读取文档的元数据:

var request = gapi.client.drive.files.get({
    fileId: id,
    key: APIKey,
});
request.then(function(response) {
    console.log("test sucess!!!");
}, handleErrors);

认证登录是这样的:

gapi.load('auth2', function() {
    auth2 = gapi.auth2.init({
        client_id: '***valid-id-comes-here***.apps.googleusercontent.com',
        fetch_basic_profile: true,
        scope: 'https://www.googleapis.com/auth/drive.file'
    });
    gapi.load('client', function() {
        gapi.client.load('drive', 'v3');
    });
});

查看上面 JSBin 中的完整工作代码。

谢谢!

这是基于查看 http 请求的有根据的猜测。

当您在没有登录用户的情况下发出请求时,您的请求中没有授权 header。 GDrive 可能会说 "dunno who the user is so is the file is public?" 并授予访问权限。通过授权 header 和访问令牌,GDrive 知道我是谁,所以说 "Has the owner granted pinnoyid access to the this file?" 答案是否定的。您可能认为 GDrive 逐步尝试 public 访问是合理的,但我可以看到这两种观点。

您的问题 "fix" 是阻止 load 函数发送授权 header 请求。

顺便说一句。我对制作精美的 JSBin 的问题投了赞成票:-)

我认为当用户通过身份验证时无法访问文件的原因是 drive.file 对应用程序施加的限制。

drive.file 的定义是应用程序具有 "Per-file access to files created or opened by the app. File authorization is granted on a per-user basis and is revoked when the user deauthorizes the app,",如 Drive API oAuth scope documentation 中所述。

应用程序无法代表用户打开文件,除非用户具有对该特定文件的特定应用程序的 g运行ted 访问权限。这是对用户访问文件的正常限制的补充...即使用户通常可以通过 Google 驱动器 GUI 读取该文件(例如,他们拥有该文件,或者该文件可以被任何拥有该文件的人读取) link),第三方应用程序需要用户额外的 g运行t 权限才能代表他们访问文件。您的 JSBin(制作精美)演示了此限制的实际效果。

您可以通过将您的 JSBin 应用程序指向您云端硬盘中的一个文件来验证这一点,该应用程序 获得 运行 访问权限。您可以使用 GAPI 的 drive.files.create 方法让应用程序在登录用户的 Drive ("a file created... by the app") 中创建一个文件。或者,您可以 integrate your application with Drive's "Open with" menu 然后在特定文件 ("a file ... opened by the app") 的 Google Drive GUI 中使用 "Open with"。执行其中任一操作后,当该用户通过身份验证时,相关文件应该可以在您的 JSBin 中读取。

有趣的是,您的 JSBin 演示了具有 drive.file oAuth 范围 的应用程序可以 匿名访问文件(如果文件可匿名查看)。这不是范围描述所期望的。

正如您在原始 post 和 pinoyyid 的回答中所讨论的那样,它至少允许在匿名可读文件的情况下进行解决:您可以手动使用 fetch()XMLHttpRequest 在不使用 Google 的 GAPI 包装器的情况下对 Google Drive REST 端点进行 REST 调用,并从请求中省略任何凭据。这将允许您的应用程序同时发出经过身份验证的请求(通过 GAPI)和匿名请求(通过您的手动 REST 请求)。

如果您希望阅读的文件未与 "anyone with a link" 共享,而是与登录用户显式共享,则此解决方法将无济于事。

编辑: 我试图在我的应用程序中实施变通方法,但使用自定义代码发出请求时出现问题 - 因为它并非源自 Google,它被视为跨站请求,我运行进入CORS问题。我最终实施的解决方案是在 iframe 中创建第二个 GAPI 客户端,我没有对其进行身份验证。 .

中可以看到我的代码示例