授权范围

用户必须授权访问其数据或代表其执行操作的脚本项目。当用户首次运行需要授权的脚本时,界面会显示一个提示,以启动授权流程。

在此流程中,界面会告知用户脚本需要哪些权限。例如,脚本可能需要读取用户电子邮件或在其日历中创建活动的权限。脚本项目会将这些单独的权限定义为 OAuth 范围

对于大多数脚本,Apps 脚本会自动检测您所需的范围;您可以随时查看脚本使用的范围。您还可以使用网址字符串在清单明确设置范围。对于某些应用(例如插件),有时需要明确设置范围,因为已发布的应用应始终使用尽可能窄的范围。

在授权流程中,Apps 脚本会向用户显示所需范围的人类可读说明。例如,如果脚本需要对电子表格拥有只读权限,则清单可能具有 https://www.googleapis.com/auth/spreadsheets.readonly 范围。在授权流程中,具有此范围的脚本会要求用户允许此应用“查看您的 Google 电子表格”。

某些范围包含其他范围。例如,当授权范围 https://www.googleapis.com/auth/spreadsheets 时,允许对电子表格进行读写访问。

对于运行脚本的某些界面(例如直接从 Apps 脚本 IDE 运行脚本),系统会向用户显示精细的 OAuth 权限请求页面。这样,用户就可以选择要授予的特定权限,而无需一次性授予所有权限。请务必设计脚本以处理精细的 OAuth 权限

查看范围

您可以执行以下操作来查看脚本项目当前所需的范围:

  1. 打开脚本项目。
  2. 点击左侧的概览图标
  3. 查看 Project OAuth Scopes(项目 OAuth 范围)下的范围。

设置明确的范围

Apps 脚本会扫描脚本的代码,查找需要范围的函数调用,从而自动确定脚本需要哪些范围。对于大多数脚本,这已足够,并且可以节省您的时间,但对于已发布的插件、Web 应用、Google Chat 应用以及对 Google Chat API 的调用,您必须对范围进行更直接的控制。

Apps 脚本有时会自动为项目分配非常宽松的范围。这可能意味着您的脚本向用户请求的权限超出了实际需要,这是一种不良做法。对于已发布的脚本,您必须将宽泛的范围替换为更有限的范围集,该范围集应仅涵盖脚本的需求。

您可以修改脚本项目的清单文件,明确设置脚本项目使用的范围。清单字段 oauthScopes 是项目使用的所有范围的数组。如需设置项目的范围,请执行以下操作:

  1. 打开脚本项目。
  2. 点击左侧的项目设置图标
  3. 选中在编辑器中显示“appsscript.json”清单文件复选框。
  4. 点击左侧的编辑器图标
  5. 点击左侧的 appsscript.json 文件。
  6. 找到标记为 oauthScopes 的顶级字段。如果不存在,您可以添加。
  7. oauthScopes 字段指定一个字符串数组。如需设置项目使用的范围,请将此数组的内容替换为您希望项目使用的范围。 例如:
          {
            ...
            "oauthScopes": [
              "https://www.googleapis.com/auth/spreadsheets.readonly",
              "https://www.googleapis.com/auth/userinfo.email"
            ],
           ...
          }
  8. 点击顶部的“保存”图标

处理精细的 OAuth 权限

通过精细的 OAuth 权限请求页面,用户可以指定他们想要授权的各个 OAuth 范围。借助精细的 OAuth 权限,用户可以更精细地控制自己选择与每个脚本共享哪些账号数据。例如,假设您开发了一个脚本,该脚本同时请求电子邮件范围和日历范围的权限。您的用户可能只想使用脚本的 Google 日历功能,而不想使用 Gmail 功能。借助精细的 OAuth 权限,用户可以选择仅授予日历权限,而不授予 Gmail 权限。

以下部分介绍了处理精细 OAuth 权限的主要方法。

自动要求为必要的范围授予权限

如果执行流程需要某些范围的权限才能正常运行,您可以要求用户先授予这些权限,然后才能使用该流程。您的脚本可以检查用户是否已授予权限,如果未授予,则自动向用户请求权限。

ScriptApp中的以下方法可让您验证所需范围的权限,并自动呈现授权提示以请求任何缺失的权限:

示例

以下示例展示了如何调用 requireScopes(authMode, oAuthScopes)requireAllScopes(authMode) 方法。 该脚本使用 Gmail、Google 表格和 Google 日历的范围。 sendEmail() 函数仅需要 Gmail 和 Google 表格的权限范围,而 createEventSendEmail() 函数需要脚本使用的所有权限范围。

// This function requires the Gmail and Sheets scopes.
function sendEmail() {
  // Validates that the user has granted permission for the Gmail and Sheets scopes.
  // If not, the execution ends and prompts the user for authorization.
  ScriptApp.requireScopes(ScriptApp.AuthMode.FULL, [
    'https://mail.google.com/',
    'https://www.googleapis.com/auth/spreadsheets'
  ]);

  // Sends an email.
  GmailApp.sendEmail("dana@example.com", "Subject", "Body");
  Logger.log("Email sent successfully!");

  // Opens a spreadsheet and sheet to track the sent email.
  const ss = SpreadsheetApp.openById("abc1234567");
  const sheet = ss.getSheetByName("Email Tracker")

  // Gets the last row of the sheet.
  const lastRow = sheet.getLastRow();

  // Adds "Sent" to column E of the last row of the spreadsheet.
  sheet.getRange(lastRow, 5).setValue("Sent");
  Logger.log("Sheet updated successfully!");
}

// This function requires all scopes used by the script (Gmail,
// Calendar, and Sheets).
function createEventSendEmail() {
  // Validates that the user has granted permission for all scopes used by the
  // script. If not, the execution ends and prompts the user for authorization.
  ScriptApp.requireAllScopes(ScriptApp.AuthMode.FULL);

  // Creates an event.
  CalendarApp.getDefaultCalendar().createEvent(
    "Meeting",
    new Date("November 28, 2024 10:00:00"),
    new Date("November 28, 2024 11:00:00")
  );
  Logger.log("Calendar event created successfully!");

  // Sends an email.
  GmailApp.sendEmail("dana@example.com", "Subject 2", "Body 2");
  Logger.log("Email sent successfully!");

  // Opens a spreadsheet and sheet to track the created meeting and sent email.
  const ss = SpreadsheetApp.openById("abc1234567");
  const sheet = ss.getSheetByName("Email and Meeting Tracker")
  // Gets the last row
  const lastRow = sheet.getLastRow();

  // Adds "Sent" to column E of the last row
  sheet.getRange(lastRow, 5).setValue("Sent");
  // Adds "Meeting created" to column F of the last row
  sheet.getRange(lastRow, 6).setValue("Meeting created");
  Logger.log("Sheet updated successfully!");
}

为缺少范围的情况创建自定义体验

您可以获取运行脚本的用户的权限详细信息,并根据其权限状态设计自定义体验。例如,您可以决定关闭脚本中需要用户尚未授予的权限的特定功能,或者显示一个自定义对话框来解释缺少哪些权限。以下方法会获取一个包含用户权限信息的对象,其中包括用户已授权的范围以及一个用于请求任何缺失范围的网址:

如需从授权信息对象中获取权限详细信息(例如已授权的范围列表和用于请求缺失权限的网址),请使用 AuthorizationInfo 类中的方法

示例

以下示例展示了如何调用 getAuthorizationInfo(authMode, oAuthScopes) 方法,以跳过执行流程中尚未授予所需范围的特定功能。这样一来,执行流程的其余部分就可以继续进行,而无需提示用户授权缺失的范围。

// This function uses the Gmail scope and skips the email
// capabilities if the scope for Gmail hasn't been granted.
function myFunction() {
  const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL, ['https://mail.google.com/']);
  if (authInfo.getAuthorizationStatus() === ScriptApp.AuthorizationStatus.NOT_REQUIRED) {
    GmailApp.sendEmail("dana@example.com", "Subject", "Body");
    Logger.log("Email sent successfully!");
  } else {
    const scopesGranted = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL).getAuthorizedScopes();
    console.warn(`Authorized scopes: ${scopesGranted} not enough to send mail, skipping.`);
  }
  // Continue the rest of the execution flow...
}

确保触发器执行具有权限

与触发器关联的函数可以在特定事件发生时自动运行,而用户可能不在场,无法提供更多权限。我们建议您先使用 requireScopes(authMode, oAuthScopes),然后再安装触发器。这会提示用户授予缺失的权限,并且不允许在没有这些权限的情况下安装触发器。

示例

// This function requires scope Sheets.
function trackFormSubmissions(e){
  // Opens a spreadsheet to track the sent email.
  const ss = SpreadsheetApp.openById("abc1234567");
  const sheet = ss.getSheetByName("Submission Tracker")

  // Gets the last row of the sheet.
  const lastRow = sheet.getLastRow();

  // Adds email address of user that submitted the form
  // to column E of the last row of the spreadsheet.
  sheet.getRange(lastRow, 5).setValue(e.name);
  Logger.log("Sheet updated successfully!");
}


function installTrigger(){
  // Validates that the user has granted permissions for trigger
  // installation and execution. If not, trigger doesn't get
  // installed and prompts the user for authorization.
  ScriptApp.requireScopes(ScriptApp.AuthMode.FULL, [
    'https://www.googleapis.com/auth/script.scriptapp',
    'https://www.googleapis.com/auth/spreadsheets',
    'https://www.googleapis.com/auth/forms.currentonly'
  ]);
  ScriptApp.newTrigger('trackFormSubmission')
    .forForm(FormApp.getActiveForm())
    .onFormSubmit()
    .create();
}

OAuth 验证

某些 OAuth 范围是敏感的,因为它们允许访问 Google 用户数据。如果脚本项目使用的范围允许访问用户数据,则该项目必须先通过 OAuth 客户端验证,然后才能作为 Web 应用或插件公开发布。如需了解详情,请参阅以下指南:

受限范围

除了敏感范围之外,某些范围还被归类为受限范围,并受有助于保护用户数据的额外规则的约束。如果您打算发布使用一个或多个受限范围的网络应用或插件,则该应用必须先遵守所有指定的限制,然后才能发布。

在尝试发布之前,请先查看受限范围的完整列表。如果您的应用使用了其中任何一个范围,您必须在发布之前遵守有关特定 API 范围的其他要求