首页 > 解决方案 > Google 服务帐户委派 404 错误

问题描述

我正在尝试使用服务帐户进行身份验证,以代表域上的用户帐户工作。我已委派管理员访问权限并添加到 GSuite 控制台。我可以使用以下内容获取访问令牌,但是发出复制驱动器文件的批处理请求返回“代码:404,消息:'找不到文件:”。下面的代码是用 Google Apps 脚本编写的。我是否遗漏了创建和验证服务帐户的过程?

    var CREDENTIALS = {
      private_key: "-----BEGIN PRIVATE KEY----- XXXXXXX \n-----END PRIVATE KEY-----\n",
      client_email: "XXXXXX@fXXXXXX.iam.gserviceaccount.com",
      client_id: "1XXXXXXXXXXXXXXXX",
      user_email: "XXXXX@XXXX.XXX.XXX",
      scopes: ["https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request"]
    };


    function oAuthToken(){
          var url = "https://www.googleapis.com/oauth2/v3/token";
          var header = {
            alg: "RS256",
            typ: "JWT",
          };
          var now = Math.floor(Date.now() / 1000);
          var claim = {
            iss: CREDENTIALS.client_id,
            sub: CREDENTIALS.user_email,
            scope: CREDENTIALS.scopes.join(" "),
            aud: url,
            exp: (now + 3600).toString(),
            iat: now.toString(),
          };
          var signature = Utilities.base64Encode(JSON.stringify(header)) + "." + Utilities.base64Encode(JSON.stringify(claim));
          var jwt = signature + "." + Utilities.base64Encode(Utilities.computeRsaSha256Signature(signature, CREDENTIALS.private_key));

          var params = {
            method: "post",
            payload: {
              assertion: jwt,
              grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
            },
          };
          var res = UrlFetchApp.fetch(url, params).getContentText();
          return JSON.parse(res)
        }

批处理过程有点粗糙,但这就是它的要点。

var request={
  batchPath:
  requests:[]
}

var backoff =0

function batch(request) {
  var oAuth=oAuthToken().access_token
  var url ='https://www.googleapis.com/'+request.batchPath
  var body =request.requests
  if(body.length<1){
    return []
  }
  var boundary = 'xxxxxxxxxx';
  var contentId = 0;
  var data = '--' + boundary + '\r\n';

  for (var i in body) {
    if(typeof body[i]=='object'){
      data += 'Content-Type: application/http\r\n';
      data += 'Content-ID: ' + ++contentId + '\r\n\r\n';
      data += body[i].method + ' ' + body[i].endpoint + '\r\n';
      data += body[i].requestBody ? 'Content-Type: application/json; charset=utf-8\r\n\r\n' : '\r\n';
      data += body[i].requestBody ? JSON.stringify(body[i].requestBody) + '\r\n' : '';
      data += "--" + boundary + '\r\n';
    }
  }

  var parseBatchRes = function(res) {
    var splittedRes = res.split('--batch');
    return splittedRes.slice(1, splittedRes.length - 1).map(function(e) {
      return {
        contentId: Number(e.match(/Content-ID: response-(\d+)/)[1]),
        status: Number(e.match(/HTTP\/\d+.\d+ (\d+)/)[1]),
        object: JSON.parse(e.match(/{[\S\s]+}/)[0]),
      };
    });
  };

  var payload = Utilities.newBlob(data).getBytes();
  var head = {Authorization: 'Bearer ' + oAuth}
  var options = {
    method: 'POST', 
    contentType: 'multipart/mixed; boundary=' + boundary,
    payload: payload,
    headers: head,
    muteHttpExceptions: false
  };
  var complete=false;
  var finalResponse=[];
  for (var n=0; n<=backoff; n++) {
    if(complete){
      break;
    }
    var complete = true
    console.log('backoff',n);
    var response =UrlFetchApp.fetch(url, options).getContentText();
    for(var j=0;j<response.length;j++){
      if(response[r].status!=200){
        var complete = false
      }
    }
  }
}

标签: google-apps-scriptservice-accounts

解决方案


supportsAllDrives = true查询参数添加到请求中。

参数指示请求的应用程序是否同时支持我的驱动器和共享驱动器,默认值为false

参考


推荐阅读