一尘不染

使用JavaScript授权Google云端硬盘

javascript

我正在尝试授权我的应用程序与Google云端硬盘集成。Google文档提供了有关基于服务器的授权的详细信息以及各种服务器技术的代码示例。

还有一个JavaScript Google API库,该库支持授权。在Wiki的示例部分下方有一个代码片段,用于创建配置和调用authorize函数。我将范围更改为我认为需要驱动器的范围:

var config = {
    'client_id': 'my_client_ID',
    'scope': 'https://www.googleapis.com/auth/drive.file'
  };
  gapi.auth.authorize(config, function() {
    console.log(gapi.auth);
  });

永远不会调用该回调函数(是的,已更正了GoogleAPI库的加载)在Java检索和使用OAuth2.0凭据示例中,客户端密码似乎是一个参数,是否应将其放入配置中?

是否有人在JS中针对Drive或其他Google API尝试过此操作?有谁知道调试此类问题的最佳途径,即我是否仅需要逐步浏览库并停止抱怨?

请不要建议在服务器端进行授权,我们的应用程序完全是客户端,我不希望服务器上有任何状态(而且我知道这会导致令牌刷新问题)。我熟悉Google控制台中的API配置,并且相信驱动器SDK设置正确。


阅读 354

收藏
2020-05-01

共1个答案

一尘不染

可以将Google APIs Javascript客户端库与Drive一起使用,但是您必须注意一些痛点。

当前有2个主要问题,都存在工作问题:

授权书

首先,如果您仔细查看Google云端硬盘身份验证的工作原理,您将意识到,在用户安装了云端硬盘应用程序并尝试使用该应用程序打开文件或创建新文件后,云端硬盘会自动启动OAuth
2.0授权流程, auth参数设置为 response_type = codeaccess_type = offline
。基本上,这意味着目前Drive应用程序被迫使用OAuth 2服务器端流,而Java客户端库(仅使用客户端流)将不会使用OAuth 2服务器端流。

问题是:Drive启动服务器端OAuth 2.0流,然后Javascript客户端库启动客户端OAuth 2.0流。

这仍然可以正常工作,您所要做的就是使用服务器端代码来处理在Drive服务器端流之后返回的授权代码(您需要将其交换为访问令牌和刷新令牌)。这样,只有在第一个流程中,才会提示用户进行授权。首次交换授权码后,身份验证页面将自动绕过。

如果您不处理/交换服务器端流程上的身份验证代码,则每次用户尝试从云端硬盘使用您的应用时,系统都会提示用户进行身份验证。

处理文件内容

第二个问题是,我们的Javascript客户端库使上传和访问实际的云端硬盘文件内容变得不容易。您仍然可以执行此操作,但是必须使用自定义Javascript代码。

读取文件内容

检索文件元数据/文件对象时,它包含一个downloadUrl指向实际文件内容的属性。现在可以使用CORS请求下载文件,并且最简单的身份验证方法是在URL参数中使用OAuth
2访问令牌。因此,只需附加&access_token=...downloadUrl并使用XHR或通过将用户转发到URL来获取文件。

上载文件内容

更新更新:现在,上传端点 确实 支持CORS。

更新:与其他Drive API不同,上传端点不支持CORS,因此您现在必须使用以下技巧:

上载文件非常棘手,因为它不是Javascript客户端库中的内置文件,并且您不能如本响应中所述完全使用HTTP来完成文件,因为我们不允许在这些API端点上进行跨域请求。因此,您必须利用我们的Javascript客户端库使用的iframe代理,并使用它将构造的多部分请求发送到DriveSDK。

/**
 * Insert new file.
 *
 * @param {File} fileData File object to read data from.
 * @param {Function} callback Callback function to call when the request is complete.
 */
function insertFileData(fileData, callback) {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  var reader = new FileReader();
  reader.readAsBinaryString(fileData);
  reader.onload = function(e) {
    var contentType = fileData.type || 'application/octet-stream';
    var metadata = {
      'title': fileData.fileName,
      'mimeType': contentType
    };

    var base64Data = btoa(reader.result);
    var multipartRequestBody =
        delimiter +
        'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter +
        'Content-Type: ' + contentType + '\r\n' +
        'Content-Transfer-Encoding: base64\r\n' +
        '\r\n' +
        base64Data +
        close_delim;

    var request = gapi.client.request({
        'path': '/upload/drive/v2/files',
        'method': 'POST',
        'params': {'uploadType': 'multipart'},
        'headers': {
          'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
        },
        'body': multipartRequestBody});
    if (!callback) {
      callback = function(file) {
        console.log(file)
      };
    }
    request.execute(callback);
  }
}

为了改善所有这些,将来我们可能:

  • 让开发人员选择他们要使用的OAuth 2.0流(服务器端还是客户端),或者让开发人员完全处理OAuth流。
  • /upload/...端点上允许CORS
  • 在本exportLinks机gDocs 上允许CORS
  • 我们应该使使用Javascript客户端库上传文件更加容易。

尽管在这一点上没有任何承诺:)

2020-05-01