javascript - 如何使用服务帐户和 Google Drive API 解决 403 错误

标签 javascript oauth oauth-2.0 google-drive-api google-oauth

我正在尝试编写一个客户端 JS 脚本,该脚本将从我的 gDrive 中获取图像以使用服务帐户显示在网站上。我创建了服务帐户并为该项目添加并启用了 google Drive API。但是当我运行脚本时,出现 403 错误:超出了未经身份验证使用的每日限制。继续使用需要注册。我认为这可能与权限或范围有关?我看过其他几个堆栈溢出,但似乎无法弄清楚。

Getting a 403 - Forbidden for Google Service Account

Google Drive service account returns 403 usageLimits

其中一些提到添加 Angular 色或范围,但我无法弄清楚如何添加它们或我需要添加哪些。 GSuite 帐户是强制性的吗?听起来我需要进入 GSuite 管理控制台来添加范围?我不想注册一个帐户,因为它不是免费的。任何帮助,将不胜感激。我的代码如下所示:


function gDrive() {
  function init(callback) {
    authorizeClient(getJWT()).then(function(token) {
      loadClient(token, callback);
    });
  }

  /* Retrieve a signed JWT */
  function getJWT() {
    // Prepare header, payload, and key
    let oHeader = {
      "alg": "RS256",
      "typ": "JWT"
    };
    let sHeader = JSON.stringify(oHeader);
    let oPayload = {
      "iss": "SERVICE ACCOUNT EMAIL",
      "sub": "SERVICE ACCOUNT EMAIL",
      "aud": "https://www.googleapis.com/oauth2/v3/token",
      "iat": KJUR.jws.IntDate.getNow(),
      "exp": KJUR.jws.IntDate.get("now + 1hour"),
      "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.readonly"
    };
    let sPayload = JSON.stringify(oPayload);
    let privKey = "-----BEGIN PRIVATE KEY-----BLAH BLAH BLAH\n-----END PRIVATE KEY-----\n";

    // Sign JWT
    return signedJWS = KJUR.jws.JWS.sign(null, sHeader, sPayload, privKey);
  }

  /* Http POST to Google Auth api */
  function authorizeClient(JWS) {
    // Request access token
    const url = "https://www.googleapis.com/oauth2/v3/token";
    let encodedData = "";
    let encodedDataPairs = [];
    encodedDataPairs.push(encodeURIComponent("grant_type") + '=' + encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"));
    encodedDataPairs.push(encodeURIComponent("assertion") + '=' + encodeURIComponent(JWS));
    encodedData = encodedDataPairs.join('&').replace(/%20/g, '+');

    const params = {
      headers: {"content-type":"application/x-www-form-urlencoded"},
      body: encodedData,
      method: "POST"
    };

    return fetch(url, params).then(accessTokenSucces).then(returnToken).catch(accessTokenFailed);
  }

  function accessTokenSucces(data) {
    console.log("Retrieved access token");
    return data.json();
  }

  function returnToken(resp) {
    return resp.access_token;
  }

  function accessTokenFailed(error) {
    console.log("Requesting access token failed: " + error);
  }

  function loadClient(accessToken, callback) {
    gapi.load('client', function() {
      console.log("loading client");
      gapi.client.setToken(accessToken);
      console.log("set access token");
      return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/drive/v3/rest").then(clientLoadSuccessful).then(callback).catch(clientLoadFailed);
    })
  }

  function clientLoadSuccessful() {
    console.log("Client loaded");
    return Promise.resolve();
  }

  function clientLoadFailed(error) {
    console.log("Loading Client failed: " + error);
    return Promise.reject();
  }

  function fetchAllImages(fileName, chapter, callback) {
    console.log("fetching images");
    let initialRequest = gapi.client.drive.files.list({"q": "mimeType contains \"image\" and name contains '" 
                                                       + fileName + "_ch" + chapter + "'"});
    retrievePageOfFiles(initialRequest, [], fileName, chapter);

    function retrievePageOfFiles(request, result) {
      request.execute(function(resp) {
        result = result.concat(resp.files);
        let nextPageToken = resp.nextPageToken;
        if (nextPageToken) {
          request = gapi.client.drive.files.list({
            "pageToken": nextPageToken,
            "q": "mimeType contains \"image\" and name contains '" + fileName + "_ch" + chapter + "'"
          });
          retrievePageOfFiles(request, result);
        } else {
          console.log("Images retrieved");
          callback(result);
        }
      }).catch(function(err) {
        console.log("Could not retrieve images: " + err);
      });
    }
  }

  return {
    init: init,
    fetchAllImages: fetchAllImages
  };
}

gDrive().init(runApp);

function runApp() {
console.log("Running App");
    gDrive().fetchAllImages("FILENAME", "1", imageCallback);
}

function imageCallback(data) {
    console.log("Images Retrieved!");
    console.log(data);
}

最佳答案

  • 当您的脚本运行时,未验证使用的每日限制已超出错误。继续使用需要注册。 发生。
  • 您想消除这个错误。

如果我的理解是正确的,这个修改怎么样?我认为可以使用您的脚本检索到的访问 token 。所以请按如下方式修改您的脚本。

来自:

gapi.client.setToken(accessToken);

收件人:

gapi.client.setToken({access_token: accessToken});

引用:

如果这不是您问题的直接解决方案,我深表歉意。

关于javascript - 如何使用服务帐户和 Google Drive API 解决 403 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59295318/

相关文章:

javascript - 在没有确认对话框的情况下取消下拉菜单的更改事件

javascript - 移动应用程序中的图像渲染

Javascript 库可在运行时优雅地降级 HTML 中的自定义元素

oauth - 雅虎日历 API (CalDav) 是否可以与 OAuth 配合使用?

django - 使用 Oauth 和 Python 授权应用程序

php - 清理 Magento Google Api OAuth2 集成

javascript - 如何在充电后调用 Laravel 中的函数?

mysql - 在我的数据库中存储 oauth key 的最佳做法是什么?

java - Google Drive Android API OAuth 身份验证问题 - onActivityResult 返回 "0"

python-2.7 - 导入错误 : No module named cryptography. hazmat.bindings._openssl