google-apps-script - 另一个 Google Apps 脚本 UrlFetchApp 返回未经授权的错误 401

标签 google-apps-script web-applications google-oauth http-status-code-401 urlfetch

因此,我使用的是包含 protected 范围的 Google 电子表格,因此,为了完成对行进行排序,从工作表中调用未绑定(bind)的 Web 应用程序:

Google Sheet XYZ -> Unbound Web App (sort code) -> Google Sheet XYZ 

Unbound Web App 在我的帐户下运行,并使用 Sheet XYZ 与用户共享。 工作完美。

现在,我尝试使用 OnSubmit 从 Google 表单调用相同的 Web 应用程序:

Google Form ABC -> Unbound Web App (sort code) -> Google Sheet XYZ 

但是,网络应用程序返回了异常:

{ [Exception: Request failed for https://script.google.com returned code 401. Truncated server response: <HTML>
<HEAD>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>
 (use muteHttpExceptions option to examine full response)] name: 'Exception' }

奇怪的是,尽管我既是表单、网络应用程序又是工作表所有者,但这种情况却发生了......还尝试向表单脚本添加其他范围。

这是在表单的OnSubmit中运行的代码:

function callWebApp(){
  var queryString = "?action=sort&sheetID="+contactListSSID+"&sortType=byName&sheetName="+S_PARENTS_SHEET_NAME+"&firstDataRow="+S_PARENTS_FIRST_DATA_ROW+"&colUserName="+S_PARENTS_NAME_SURNAME_COLUMN+"&classColSection="+null+"&colDOB="+null; // null because unused for this sort type
  var baseUrl ="https://script.google.com/a/macros/ourdomain.com/s/xxxxxxx/exec"
  var url = encodeURI(baseUrl + queryString).replace("#","%23");
  var params = {method: "get", headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()}};
  
  try {
      var request = UrlFetchApp.fetch(url,params)
      Logger.log(request);
  } catch (error) {
    console.error(error);
    return error;
  }
  return request;
}

未绑定(bind)的 Web 应用程序代码(不包括代码中列出的所有操作):

function doGet(e) {
  var param = e.queryString;
  var parameters = param.split("&") 
  var validActions = ["sort", "duplicate", "delete"];
  if (param == null){
    return "Missing parameters";
  }
  param = e.parameter;
  const matches = parameters.filter(s => s.includes('action'));
  if (matches.length < 1 || validActions.indexOf(param.action) < 0){
    return "Missing or bad action";
  }
  var ret;
  switch(param.action){
    case "sort":
      ret = sortSheet(e);
      break;
    case "duplicate":
      ret = duplicateSheet(e);
      break;
    case "delete":
      ret = deleteSheet(e);
      break;  
  }

  return ContentService.createTextOutput(ret);
}

function sortSheet (e){
  param = e.parameter;
  var sheetId = param.sheetID;
  var name = param.sheetName;
  var sortType = param.sortType;
  var COL_STUDENT_NAME = Number(param.colUserName);
  var S_CLASS_COL_SECTION = Number(param.classColSection);
  var COL_DOB = Number(param.colDOB);
  var FIRST_DATA_ROW = Number(param.firstDataRow);
  try{  
    var ss = SpreadsheetApp.openById(sheetId)  
    var sheet = ss.getSheetByName(name)
    var dataRange = sheet.getRange(FIRST_DATA_ROW,1,(sheet.getLastRow() - FIRST_DATA_ROW + 1),sheet.getMaxColumns()); 
    var a1 = dataRange.getA1Notation();
    
    switch (sortType){
      case "byName":
        dataRange.sort({column: COL_STUDENT_NAME, ascending: true});
        break;
      case "bySection":
        dataRange.sort([{column: S_CLASS_COL_SECTION, ascending: true}, {column: COL_STUDENT_NAME, ascending: true}]);
        break;  
      case "byDOB":
        dataRange.sort([{column: COL_DOB, ascending: true}, {column: COL_STUDENT_NAME, ascending: true}]);
        break;   
    }
  }
    catch (err){
    return err;
  }
  return a1;
}

当上述代码从电子表格运行时,它可以工作。一旦在表单中运行相同的代码,就会抛出异常。

最佳答案

问题:

需要 drive 范围才能访问非公共(public) Apps 脚本 Web 应用。

解决方案:

添加这两个范围中的任何一个都可以:

您可以添加它们 explicitly in the manifest ,使用字段oauthScopes:

"oauthScopes": [
  "https://www.googleapis.com/auth/script.external_request", 
  "https://www.googleapis.com/auth/script.scriptapp",
  "https://www.googleapis.com/auth/forms",
  "https://www.googleapis.com/auth/drive.readonly"
]

或者,更简单的是,您可以添加注释行以及需要此范围的方法,例如:

//DriveApp.getFileById()

脚本会注意到这一点,因此 ScriptApp.getOAuthToken() 将获得此范围的授权。

相关:

关于google-apps-script - 另一个 Google Apps 脚本 UrlFetchApp 返回未经授权的错误 401,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72042819/

相关文章:

google-apps-script - 将 *.googleusercontent.com 添加到 Authorized JavaScript origins

javascript - 在二维数组上运行 .map() 后如何用数据填充列

asp.net - "object reference not set"在 Visual Studio 2010 中的 asp.net default.aspx 文件的设计 View 中显示

python - 导入 "google.oauth2.credentials"无法解析 Visual Studio Code

google-apps-script - Google 云端硬盘第三方快捷方式的工作原理

google-apps-script - 具有混合二进制和文本负载的 Google Apps 脚本 UrlFetchApp()

web-applications - 有没有关于网站架构(不是 UI 设计)的好书?

android - Web 应用程序可以控制 native 操作系统控件吗?

javascript - Google OAuth - 使用 "anonymous"作为 key 和 secret 是否不安全?

java - 如何从 Google id_token 检索名称属性