本指南介绍了在 Apps 脚本中调用 API 时如何使用服务账号进行身份验证。
服务账号是一种由应用(而非个人)使用的特殊账号。您可以使用服务账号通过机器人账号访问数据或执行操作,也可以代表 Google Workspace 或 Cloud Identity 用户访问数据。如需了解详情,请参阅 了解服务账号。如需大致了解 Google Workspace API 的身份验证,请参阅 创建访问凭据。
何时在 Apps 脚本中使用服务账号
默认情况下,Apps 脚本使用脚本用户的凭据调用 API。如果您使用
UrlFetchApp调用 Google API,则可以通过调用
ScriptApp.getOAuthToken获取脚本用户的
访问令牌。
不过,在某些情况下,使用服务账号比使用 ScriptApp.getOAuthToken 有几个优势。出于以下原因,请考虑使用服务账号身份验证:
- 使用 Google Cloud API 和服务时性能更好:许多 Google Cloud API 都是为服务账号身份验证而设计的。 服务账号还可以提供一种更集成、更可靠、更安全的方式来与大多数 API 进行交互。
- 权限分离:服务账号拥有自己的权限,
与任何用户分开。当您与其他用户共享项目时,身份验证方法
ScriptApp.getOAuthToken可能会失败。通过使用服务账号,共享脚本并 将其发布为 Google Workspace 插件。 - 自动化脚本和长时间运行的任务:服务账号可让您运行 自动化脚本、批处理或后台任务,而无需用户输入。
- 增强的安全性和最小权限原则:向服务账号授予特定权限,仅提供对所需资源的访问权限。这遵循了最小权限原则,可降低
安全风险。使用
ScriptApp.getOAuthToken通常会向脚本授予所有用户权限,这可能过于宽泛。 - 集中式访问权限管理:服务账号使用 Google Cloud 的 身份和访问权限管理 (IAM)进行管理。 IAM 可帮助 Google Workspace 组织管理对 Apps 脚本项目中的已通过身份验证的服务的访问权限。
前提条件
- 具有一个 Google Cloud 项目。
- 在 Cloud 项目中, 启用您要 使用服务账号凭据进行身份验证的任何 API。
- 如需向服务账号分配角色,您必须拥有 超级用户 权限。
创建服务账号
在 Cloud 项目中,创建一个服务账号:
Google Cloud 控制台
- 在 Google Cloud 控制台中,依次点击菜单 > IAM 和管理 > 服务账号。
- 点击创建服务账号 。
- 填写服务账号详细信息,然后点击创建并继续 。
- 可选:向您的服务账号分配角色,以授予对 Google Cloud 项目资源的访问权限。如需了解详情,请参阅授予、更改和撤消对资源的访问权限。
- 点击继续 。
- 可选:输入可以管理此服务账号并使用此服务账号执行操作的用户或群组。如需了解详情,请参阅管理服务账号模拟。
- 点击完成 。记下服务账号的电子邮件地址。
gcloud CLI
- 创建服务账号:
gcloud iam service-accounts createSERVICE_ACCOUNT_NAME\ --display-name="SERVICE_ACCOUNT_NAME" - 可选:向您的服务账号分配角色,以授予对 Google Cloud 项目资源的访问权限。如需了解详情,请参阅授予、更改和撤消对资源的访问权限。
向服务账号分配角色
您必须通过超级用户账号向服务账号分配预先创建的角色或自定义角色。
在 Google 管理控制台中,依次点击菜单 > 账号 > 管理员角色。
将光标指向要分配的角色,然后点击分配管理员角色 。
点击分配服务账号 。
输入服务账号的电子邮件地址。
依次点击添加 > 分配角色。
为服务账号创建凭据
您需要以公钥/私钥对的形式获取凭据。您的代码使用这些凭据来授权应用中的服务账号操作。如需获取服务账号的凭据,请执行以下操作:
- 在 Google Cloud 控制台中,依次点击菜单 > IAM 和管理 > 服务账号。
- 选择您的服务账号。
- 依次点击密钥 > 添加密钥 > 创建新密钥。
- 选择 JSON ,然后点击 创建 。
系统会生成新的公钥/私钥对,并将其作为新文件下载到您的 计算机。将下载的 JSON 文件另存为您的工作目录中的
credentials.json。此文件是该密钥的唯一副本。如需了解如何安全地存储密钥,请参阅管理服务账号密钥。 - 点击关闭 。
复制 Cloud 项目编号
- 在 Google Cloud 控制台中,依次点击菜单 > IAM 和管理 > 设置。
- 在项目编号 字段中,复制相应值。
在 Apps 脚本项目中设置服务账号身份验证
本部分介绍了如何将云项目中的服务账号凭据添加到 Apps 脚本项目。
在 Apps 脚本中设置云项目
前往 Apps 脚本以打开或创建项目:
在 Apps 脚本项目中, 点击 项目设置
。
在 Google Cloud 项目 下,点击 更改项目。
在 Google Cloud 项目编号 中,粘贴 Cloud 项目编号。
点击设置项目 。
将凭据另存为脚本属性
通过将服务账号凭据另存为 Apps 脚本项目设置中的脚本属性,安全地存储这些凭据:
- 复制您在上一部分中创建的服务账号 JSON 文件 (
credentials.json) 的内容。 - 在 Apps 脚本项目中,前往 项目设置 。
- 在项目设置 页面中,前往脚本属性 ,然后点击添加脚本属性 并输入以下内容:
- 在属性 字段中,输入
SERVICE_ACCOUNT_KEY。 - 在值 字段中,粘贴 JSON 密钥文件的内容。
- 在属性 字段中,输入
- 点击保存脚本属性 。
添加 OAuth2 库
如需处理 OAuth2 身份验证流程,请使用 Apps 脚本
库
apps-script-oauth2。
如需将库添加到 Apps 脚本项目,请执行以下操作:
- 在 Apps 脚本编辑器中,点击左侧 库 旁边的添加库 。
- 在脚本 ID 字段中,输入
1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF。 - 点击查找 。
- 选择最新版本,然后点击添加 。
使用服务账号凭据调用 API
如需使用 Apps 脚本项目中的服务账号凭据,您可以使用以下函数 getServiceAccountService():
/**
* Get a new OAuth2 service for a given service account.
*/
function getServiceAccountService() {
const serviceAccountKeyString = PropertiesService.getScriptProperties()
.getProperty('SERVICE_ACCOUNT_KEY');
if (!serviceAccountKeyString) {
throw new Error('SERVICE_ACCOUNT_KEY property is not set. ' +
'Please follow the setup instructions.');
}
const serviceAccountKey = JSON.parse(serviceAccountKeyString);
const CLIENT_EMAIL = serviceAccountKey.client_email;
const PRIVATE_KEY = serviceAccountKey.private_key;
// Replace with the specific scopes required for your API.
const SCOPES = ['SCOPE'];
return OAuth2.createService('ServiceAccount')
.setTokenUrl('https://oauth2.googleapis.com/token')
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
.setPropertyStore(PropertiesService.getScriptProperties())
.setScope(SCOPES);
}
将 SCOPE 替换为调用 API 所需的
授权范围。该脚本使用您在上一步中另存为 SERVICE_ACCOUNT_KEY 脚本属性的服务账号凭据。
然后,您可以使用这些凭据调用 API,如以下
使用 UrlFetch 服务的示例所示:
function callApi() {
const service = getServiceAccountService();
// TODO(developer): Replace with the payload
const payload = {};
// TODO(developer): Replace with the API endpoint
const response = UrlFetchApp.fetch('API_URL', {
method: 'post',
headers: {
'Authorization': `Bearer ${service.getAccessToken()}`,
'Content-Type': 'application/json',
},
payload: payload,
});
const result = JSON.parse(response.getContentText());
return result;
}
将 API_URL 替换为您要调用的 HTTP 端点。