介绍
您是开发人员,但是使用Google API的完整初学者吗?该系列适合您,因为我向您展示了如何从头开始,从Google Workspace(“ GWS”)API(例如Google Drive和Sheets)开始。 first post涵盖了使用任何 google apis的基本要求: authentication (“ authn”)和授权(“ authz”)。通过拥有带有适当申请credentials的developer project的credentials的credentials。
second post概述了使用Google API的下一步:选择开发语言和API,使用适当的客户端库,并在DevConsole中启用所选的API。对于编程语言,我选择了 python 和 node.js ,然后选择了Google Drive API来制作一个简单的脚本,该脚本将Google Drive中的前100个文件/文件夹丢弃。启用驱动器API并安装客户端库后,您就可以编码。
我对这篇第三次也是最长的帖子感到兴奋,这不仅是因为它完成了三部分系列,而且因为我终于可以显示一些代码!虽然我对Python最舒服,但我也在学习节点,因此我很高兴能够以两种语言来演示“相同”脚本。但是,让我们先从python开始。
Python
下一部分描述了Python脚本的主要部分。该代码在http://g.co/codelabs/gsuite-apis-intro的CodeLab中更详细地描述,但是,它基于较旧的Python auth库,而所有Drive API documentation都已切换到了较新的库。无论如何,这篇文章给您足够的信息,以了解脚本koude0如何工作。
进口
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2 import credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient import discovery
标准库import
首先出现,__future__.print_function
通过将python 3 print()
函数带入Python 2应用程序,从而启用Python 2-3兼容性。 (在Python 3中忽略了此导入。
下一个块导入与GWS API交谈所需的所有软件包,包括Google APIS客户端库(googleapiclient
)和所需的安全库。
安全
代码段
creds = None
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
TOKENS = 'storage.json'
if os.path.exists(TOKENS):
creds = credentials.Credentials.from_authorized_user_file(TOKENS)
if not (creds and creds.valid):
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'client_secret.json', SCOPES)
creds = flow.run_local_server()
with open(TOKENS, 'w') as token:
token.write(creds.to_json())
许可范围
SCOPES
代表应用程序将从最终用户请求的权限;它是单个字符串或一系列此类字符串(Python list
)。在这种情况下,这是一个代表Google驱动器元数据读取权限范围的字符串。虽然它看起来像一个URL,但它被翻译为浏览器或计算机语言环境指定的语言的句子。在英语中,它将是:“请参阅有关您的Google Drive文件的信息。” 有关您自己的应用程序,范围将根据其使用的GWS API而有所不同。
例如,我还有另一个脚本可以访问驱动器和表API以及Google Cloud(GCP)存储和视觉API(请参阅this blog post),其中sample app的范围看起来像这样:
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage.full_control',
'https://www.googleapis.com/auth/cloud-vision',
'https://www.googleapis.com/auth/spreadsheets',
)
在此示例中,驱动器范围请求略有不同:是的,它也是仅读取的,但是该范围不是文件元数据,而不是文件元数据,而是访问文件 content 的权限。对于GC和表格,两个范围都是读写的,而Cloud Vision API仅处理数据(不读取或编写个人数据)。
Oauth流动
上一篇文章指示您在创建OAuth客户端ID(和SECRET)之后下载JSON凭据文件,将其保存在本地文件系统中,为client_secret.json
。连接到Google服务器请求API访问时,将与脚本所请求的范围一起介绍它们(InstalledAppFlow.from_client_secrets_file()
)。一旦用户允许访问权限,OAuth Tokens(creds
)将被发送回并存储在本地代币存储文件(TOKENS
)中。这些OAuth代币是访问Google API所需的,并且它们在本地加缓存,因此每次执行脚本时都不会提示用户。
有一对oauth令牌(访问令牌和刷新令牌):访问令牌提供API访问,但在刷新令牌不过期的情况下到期(但是可以被撤销)。如果访问令牌已过期,则使用刷新令牌请求新的(非预期)访问令牌。有关整个流程的更多信息可以在Google's documentation中找到。
刚才描述的都是如何工作的,但这是您在脚本中看到的:
- 检查现有的令牌存储文件,如果是,请加载其内容
- 检查是否存在凭据(两个oauth2令牌)并且有效
- 如果存在凭据但已过期,请使用刷新令牌请求另一个有效(访问)令牌
- 如果不存在凭据,请创建“ oauth flow”并渲染到authz的最终用户
- 不管如何获得凭据,(重新)保存最新令牌(最后几行)
应用
DRIVE = discovery.build('drive', 'v3', credentials=creds)
files = DRIVE.files().list().execute().get('files', [])
for f in files: # 4 fields returned: mimeType, kind, id, name
print(f['name'], f['mimeType'])
有趣的故事:实际应用程序所占用的代码线少于实现上述必要的安全性。第一行为Google Drive API创建了一个终点(V3是当前版本)。将其视为“ API客户端”。第二行从可通过API获得的方法收集的files()
收集中调用list()
,并返回文件列表。然后将文件用文件名和模拟型显示。如果在用户的Google驱动器中找不到文件/文件夹,则分配一个空数组(list
),没有显示任何内容。
就是这样,在这里没有其他代码行。该脚本及其较旧的Auth库等效(koude14)在Codelab中的特征可以在https://github.com/wescpy/gsuite-apis-intro的仓库中的python
文件夹中找到。现在让我们看一下节点版本。
node.js/javascript
脚本的node.js版本是文件,koude16:
进口
const fs = require('fs').promises;
const path = require('path');
const process = require('process');
const {authenticate} = require('@google-cloud/local-auth');
const {google} = require('googleapis');
标准node.js文件系统(fs
),filepath(path
)和process
软件包与Google Auth和API客户端库一起导入。如果您喜欢ES模块样式,以下是您在koude21中找到的等效import
语句:
import fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import {authenticate} from '@google-cloud/local-auth';
import {google} from 'googleapis';
下面的其余代码在两个JavaScript版本中都是相同的。
安全
等效的JavaScript安全代码与Python版本完全一样。唯一的区别是,安全步骤被分解为其自己的async
函数,因此还有更多代码可以查看:
async function loadSavedCredentialsIfExist() {
try {
const content = await fs.readFile(TOKEN_PATH);
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}
async function saveCredentials(client) {
const content = await fs.readFile(CREDENTIALS_PATH);
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: 'authorized_user',
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
access_token: client.credentials.access_token,
});
await fs.writeFile(TOKEN_PATH, payload);
}
async function authorize() {
var client = await loadSavedCredentialsIfExist();
if (client) return client;
client = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client.credentials) await saveCredentials(client);
return client;
}
典型的用法模式是对authorize()
的呼叫,请按照您要运行的代码(在我们的情况下解决承诺后),在我们的情况下通过下面显示的listFiles()
函数进行实际应用程序。
应用
async function listFiles(authClient) {
const drive = google.drive({version: 'v3', auth: authClient});
const res = await drive.files.list();
const files = res.data.files || [];
for (let file of files) {
console.log(`${file.name} (${file.mimeType})`);
}
}
authorize().then(listFiles).catch(console.error);
像Python版本一样,listFiles()
创建一个驱动器API客户端并调用其files.list()
方法。只要返回至少一个文件/文件夹,就会显示文件名和模仿。脚本中的最后一行包括“主”应用程序,称为authorize()
以获取传递给listFiles()
的凭据。就是这样,您在这里看不到其他代码行。这两个脚本都可以在https://github.com/wescpy/gsuite-apis-intro的Repo的nodejs
文件夹中找到。
打字稿注释
,由于
JSONClient
和OAuth2Client
类型之间的冲突,您将其中一些移植到打字稿可能会遇到一些挑战。具体来说,此错误可能会显示:error TS2322: Type 'OAuth2Client' is not assignable to type 'JSONClient'. Type 'OAuth2Client' is missing the following properties from type 'Impersonated': sourceClient, targetPrincipal, targetScopes, delegates, and 3 more.
我发现触摸此主题的唯一线索是在此closed bug on GH中。如果您能够获得工作版本,请在下面给我发表评论,我将更新此帖子。
运行脚本
现在编码完成了,是时候通过执行脚本来获得奖励了。执行有两个阶段。首先是通过安全过程。完成后,代码将运行。如果执行之间未发生权限更改,则安全流只能在初始执行时发生一次。之后,Oauth令牌是“自我管理:”
- 如果访问令牌仍然有效,则执行为正常
- 如果访问令已过期,则用于请求新访问令牌的刷新令牌;执行收益
无论如何,这些步骤并没有暴露于只有一次初始权限的最终用户。让我们看看这些步骤在实践中的外观。
Authn和Authz
第一次执行脚本时,用户Muse authenticate (登录或选择签署的Google帐户),然后授权该应用程序,授予它请求的许可。对于当时的Authn部分,您将获得一个Google帐户 - 选择器,可以从中选择您要使用的一个,看起来像这样: