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

问题描述 投票:1回答:1

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

Getting a 403 - Forbidden for Google Service Account

Google Drive service account returns 403 usageLimits

他们中有些提到添加角色或作用域,但我不知道如何添加它们或需要添加哪些角色或作用域。 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);
}
javascript oauth oauth-2.0 google-drive-api google-oauth2
1个回答
1
投票
  • 运行脚本时,发生Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.错误。
  • 您要删除此错误。

如果我的理解是正确的,那么该修改如何?我认为可以使用通过脚本检索的访问令牌。因此,请按如下所示修改脚本。

发件人:

gapi.client.setToken(accessToken);

收件人:

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

参考:

如果这不是您问题的直接解决方案,对不起。

© www.soinside.com 2019 - 2024. All rights reserved.