Javascript 与登录用户一起访问共享文档会导致“找不到文件”错误,但不会进行身份验证

Javascript 与登录用户一起访问共享文档会导致“找不到文件”错误,但不会进行身份验证,javascript,google-api,google-drive-api,google-api-js-client,Javascript,Google Api,Google Drive Api,Google Api Js Client,我用来阅读某人的共享(只读)文档。文档是全局共享的,任何具有链接的人都可以查看内容。有了共享url(如),我可以在浏览器中与登录用户一起查看文档,而无需任何用户(匿名模式)。只要没有用户参与,就可以使用javascript访问文档。成功登录(见下文)后,服务器会以“未找到文件”(404)错误进行响应。注销后,我可以再次访问同一文档 如果我使用curl从命令行发送相同的请求,但没有Authorization:Bearer…header,则响应为200,OK。对于授权头,响应是404 此处的工作代码

我用来阅读某人的共享(只读)文档。文档是全局共享的,任何具有链接的人都可以查看内容。有了共享url(如),我可以在浏览器中与登录用户一起查看文档,而无需任何用户(匿名模式)。只要没有用户参与,就可以使用javascript访问文档。成功登录(见下文)后,服务器会以“未找到文件”(404)错误进行响应。注销后,我可以再次访问同一文档

如果我使用curl从命令行发送相同的请求,但没有
Authorization:Bearer…
header,则响应为200,OK。对于授权头,响应是404

此处的工作代码:

如果我有一个有效/已登录的用户,我如何访问共享文档???
(不可通过电子邮件发送邀请或与特定用户共享。)

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

加载的SDK:

<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>
身份验证和登录如下所示:

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请求的有根据的猜测

在没有登录用户的情况下发出请求时,请求中没有授权标头。GDrive可能会说“不知道用户是谁,所以文件是公共的?”并授予访问权限。通过授权头和访问令牌,GDrive知道我是谁,因此会说“所有者是否已授予pinnoyid访问此文件的权限?”答案是“否”。您可能认为GDrive逐步尝试公共访问是合理的,但我可以看到这两种观点

解决问题的“方法”是停止
load
函数随请求发送授权标头


顺便说一句,我把这个问题投给了制作精美的JSBin:-)

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

drive.file
的定义是,应用程序“对应用程序创建或打开的文件具有每个文件的访问权限。文件授权基于每个用户授予,并在用户取消应用程序授权时撤销”,如中所述

应用程序无法代表用户打开文件,除非用户已授予该特定文件对该特定应用程序的访问权限。这是对用户访问文件的正常限制的补充。。。即使用户通常可以通过Google Drive GUI读取该文件(例如,他们拥有该文件,或者任何人都可以通过该链接读取该文件),第三方应用程序也需要获得用户的额外授权才能代表他们访问该文件。您的JSBin(它确实是精心制作的)在实际操作中演示了这一限制

您可以通过将JSBin应用程序指向驱动器中该应用程序已被授予访问权限的文件来验证这一点。您可以使用GAPI的
drive.files.create
方法使应用程序在登录用户的驱动器中创建文件(“应用程序创建的文件”)。或者,您可以在特定文件(“应用程序打开的文件”)上使用Google Drive GUI中的“打开方式”。执行上述任一操作后,当用户通过身份验证时,相关文件在JSBin中应该是可读的

有趣的是,您的JSBin演示了一个具有
drive.file
oAuth作用域的应用程序可以匿名访问一个文件,前提是它可以匿名查看。这不是范围描述所期望的

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

但是,如果您希望读取的文件未与“具有链接的任何人”共享,而是与登录用户显式共享,则此解决方案将不会对您有所帮助


编辑:我试图在我的应用程序中实现解决方案,但使用自定义代码发出请求时出现问题-因为它不是来自Google,被视为跨站点请求,我遇到了CORS问题。我最终实现的解决方案是在iframe中创建第二个GAPI客户机,我没有对其进行身份验证。我的代码示例可以在中看到。

谢谢您的投票!我认为没有理由阻止经过身份验证的用户访问与任何人共享的内容(
anyoneWithLink
)。这毫无意义。看看我接下来的笔记,为什么我不能停止发送auth头。就像我说的,我可以看到这两种观点。您是否有理由无法捕获404并在删除授权标头的情况下重试?没有理由。我怎么能这么做?(在请求的构造函数中尝试了
键,但没有使用。)抱歉,我没有使用jquery。我建议问一个单独的问题,标记为“jquery”,关于如何设置加载函数的标题和捕获特定的状态代码。我正在开发一个web应用程序,它可以处理存储在Google Drive中的文件。这些文档可以共享。像JSBin或JSFiddle一样思考。您收到一个url,可以看到该文档的内容。无论你是否登录。如果要保存编辑,必须登录到s
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');
    });
});