You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Google Apps Script每周重复授权问题?

问题

我编写了一个关联Google表格的Google Apps Script,用于将表格数据导出为JSON文件,供自己开发的Android应用通过Web App的/exec链接访问。我需要数据公开可访问,无需用户在应用或浏览器中授权,因此将其设置为以部署者身份运行、允许任何人匿名访问。该设置最初可正常工作,但约一周后就会提示我重新授权。

配置截图

  • Apps Script界面截图:The apps script
  • 部署配置截图:The deployment configuration

脚本代码

function doGet() {
  var sheetName = "EDIT"; // Replace with the name of your sheet
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);

  if (!sheet) {
    return {
      error: "Sheet not found."
    };
  }

  var data = sheet.getDataRange().getValues().map(([a,,c,d,e,f,g,,i,j,,,,,o,,q,r,s,t,u,v]) => [a,c,d,e,f,g,i,j,o,q,r,s,t,u,v]);
  var headers = data[0];
  var jsonData = [];

  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    var rowObject = {};

    for (var j = 0; j < headers.length; j++) {
      rowObject[headers[j]] = row[j];
    }

    jsonData.push(rowObject);
  }

  console.log(jsonData)

  return ContentService.createTextOutput(JSON.stringify(jsonData))
    .setMimeType(ContentService.MimeType.JSON);
}

function myFunction() {
doGet();  
}

appscript.json配置

{
  "timeZone": "Europe/Berlin",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "sheets": {
    "macros": [
      {
        "menuName": "sort",
        "functionName": "sort",
        "defaultShortcut": "Ctrl+Alt+Shift+1"
      }
    ]
  },
  "webapp": {
    "executeAs": "USER_DEPLOYING",
    "access": "ANYONE_ANONYMOUS"
  },
  "executionApi": {
    "access": "MYSELF"
  }
}

我了解这是Google的安全措施,但希望避免每周重新授权。我已尝试多数建议(包括正式部署应用),但仍无法长期解决。有人提到发布可能有效,但Google要求提交大量信息,请问是否有其他解决方案?


解决方案

1. 改用服务账号访问表格(最稳定方案)

绕开个人账号的授权过期限制,使用独立的服务账号对接表格:

  • 登录Google Cloud Console,创建新项目后,在「IAM与管理」>「服务账号」中生成新的服务账号。
  • 为服务账号下载JSON格式的密钥文件,妥善保存。
  • 在目标Google表格的共享设置中,添加服务账号的邮箱地址,赋予「查看者」或「编辑者」权限(按需选择)。
  • 修改Apps Script代码,通过OAuth2库使用服务账号认证访问表格:
    function doGet() {
      // 替换为你的服务账号密钥内容
      var serviceAccountKey = {
        "type": "service_account",
        "project_id": "你的项目ID",
        "private_key_id": "你的私钥ID",
        "private_key": "-----BEGIN PRIVATE KEY-----\n你的私钥内容\n-----END PRIVATE KEY-----\n",
        "client_email": "你的服务账号邮箱",
        "client_id": "你的客户端ID",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_x509_cert_url": "你的证书URL"
      };
    
      // 加载OAuth2库(需提前添加,库ID:1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF)
      var service = OAuth2.createService('SheetService')
        .setTokenUrl('https://oauth2.googleapis.com/token')
        .setPrivateKey(serviceAccountKey.private_key)
        .setIssuer(serviceAccountKey.client_email)
        .setPropertyStore(PropertiesService.getScriptProperties())
        .setScope('https://www.googleapis.com/auth/spreadsheets.readonly'); // 只读权限足够则用此,需编辑换spreadsheets
    
      if (service.hasAccess()) {
        var spreadsheetId = "你的表格ID"; // 替换为目标表格ID
        var range = "EDIT!A:Z"; // 替换为需要读取的范围
        var url = `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${range}`;
        var response = UrlFetchApp.fetch(url, {
          headers: { 'Authorization': 'Bearer ' + service.getAccessToken() }
        });
        var rawData = JSON.parse(response.getContentText()).values;
    
        // 复用原有数据转换逻辑
        var headers = rawData[0];
        var jsonData = [];
        for (var i = 1; i < rawData.length; i++) {
          var row = rawData[i];
          var rowObject = {};
          for (var j = 0; j < headers.length; j++) {
            rowObject[headers[j]] = row[j] || "";
          }
          jsonData.push(rowObject);
        }
    
        return ContentService.createTextOutput(JSON.stringify(jsonData))
          .setMimeType(ContentService.MimeType.JSON);
      } else {
        return ContentService.createTextOutput(JSON.stringify({error: service.getLastError()}))
          .setMimeType(ContentService.MimeType.JSON);
      }
    }
    

2. 缩小权限范围

当前脚本默认请求完整的Google Sheets权限,缩小权限范围可降低安全触发概率:

  • 在appscript.json中添加明确的只读权限声明:
    "oauthScopes": [
      "https://www.googleapis.com/auth/spreadsheets.readonly"
    ]
    
  • 重新部署Web App,授权时仅请求只读权限,减少安全机制的敏感度。

3. 设置定期触发保持授权有效

创建每日定时触发器,让脚本定期执行,避免因长期闲置导致授权过期:

  • 在Apps Script编辑器左侧点击「触发器」图标,添加新触发器。
  • 选择doGet函数,事件源选「时间驱动」,类型选「每天」,设置固定时间运行。

4. 检查异常日志

查看Apps Script执行日志(「查看」>「日志」),如果存在频繁错误请求(如异常IP、过量调用),会被判定为风险操作导致授权提前过期。优化请求逻辑,避免不必要的重复调用。


内容的提问来源于stack exchange,提问作者dennisklad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 04:13:13