node.js - 通过服务帐户访问 Google Drive:错误:需要登录
问题描述
const {google} = require('googleapis');
let drive = google.drive('v3');
exports.handler = async (req, res) => {
res.set('Access-Control-Allow-Origin', '*')
.set('Access-Control-Allow-Methods', 'POST')
.status(200);
var privatekey
var jwtClient
await global.admin.database().ref(`g_drive_token/OfficServiceAccount`).once('value').then((doc)=> {
privatekey = doc.val()
jwtClient = new google.auth.JWT(
privatekey.client_email,
null,
privatekey.private_key,
['https://www.googleapis.com/auth/drive.file'],
null);
console.log(JSON.stringify(jwtClient))
authWithServicePrivateKey(jwtClient)
return "null"
}) .catch((error)=> {
console.log('Error fetching user data:+', error);
return "null"
})
function authWithServicePrivateKey(jwtClient){
//authenticate request
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log("Could not connect***!"+err);
return;
} else {
console.log("Successfully connected!");
console.log('token******'+JSON.stringify(tokens))
listFolderInGoogleDrive()
CreateFolderInGoogleDrive()
}
});
}
//Google Drive API
function listFolderInGoogleDrive() {
console.log('listFolderInGoogleDrive() was called')
drive.files.list({
auth: jwtClient,
pageSize: 10,
fields: 'nextPageToken, files(id, name)',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
console.log(JSON.stringify(res.data))
console.log(JSON.stringify(res.data.files))
const files = res.data.files;
if (files.length) {
console.log('Files:');
files.map((file) => {
console.log(`${file.name} (${file.id})`);
});
} else {
console.log('No files found.');
}
});
}
function CreateFolderInGoogleDrive() {
console.log('CreateFolderInGoogleDrive() was called')
var fileMetadata = {
auth: jwtClient,
'name': 'OfficService',
'mimeType': 'application/vnd.google-apps.folder',
'parents':['12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR']
};
drive.files.create({
resource: fileMetadata,
fields: 'id'
},(err, file)=> {
if (err) {
// Handle error
console.error(err);
} else {
console.log('***parent****'+ file.data.id)
}
});
}
注意:驱动器文件夹“12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR”已与服务帐户电子邮件 ID 共享。
以下是控制台日志的一些结果,这些结果反映了它失败的位置。
token******{"access_token":"**********","token_type":"Bearer","expiry_date":1593865140000,"refresh_token":"jwt-placeholder"}
listFolderInGoogleDrive() 被调用
CreateFolderInGoogleDrive() 被调用
错误:需要登录
我想,我没有使用令牌进行身份验证。请帮助我使用 Node.js 代码使用此令牌来验证服务帐户。
解决方案
我想修改以下修改。
修改点:
- 在
exports.handler = async (req, res) => {}
,}
不使用最后一个。所以你的脚本不完整。请注意这一点。- 根据您的问题,我认为这可能是脚本的错误副本。
- 在您的脚本中,
jwtClient
不使用 atlistFolderInGoogleDrive()
和CreateFolderInGoogleDrive()
。我认为这可能是您的问题的原因。 - At
CreateFolderInGoogleDrive()
,auth: jwtClient
必须用在 的对象中{resource: fileMetadata, fields: "id"}
。- 但在这种情况下,我想建议包含
jwtClient
在drive
like中google.drive({ version: "v3", auth: jwtClient })
。
- 但在这种情况下,我想建议包含
当以上几点反映到您的脚本时,它变成如下。在这种情况下, 和 的功能authWithServicePrivateKey
被listFolderInGoogleDrive
修改CreateFolderInGoogleDrive
。
修改后的脚本:
function authWithServicePrivateKey(jwtClient) {
// Modified
jwtClient.authorize(function (err) {
if (err) {
console.log("Could not connect***!" + err);
return;
}
});
drive = google.drive({ version: "v3", auth: jwtClient }); // Added
listFolderInGoogleDrive();
CreateFolderInGoogleDrive();
}
//Google Drive API
function listFolderInGoogleDrive() {
console.log("listFolderInGoogleDrive() was called");
drive.files.list(
{
// auth: jwtClient, // Removed
pageSize: 10,
fields: "nextPageToken, files(id, name)",
},
(err, res) => {
if (err) return console.log("The API returned an error: " + err);
console.log(JSON.stringify(res.data));
console.log(JSON.stringify(res.data.files));
const files = res.data.files;
if (files.length) {
console.log("Files:");
files.map((file) => {
console.log(`${file.name} (${file.id})`);
});
} else {
console.log("No files found.");
}
}
);
}
function CreateFolderInGoogleDrive() {
console.log("CreateFolderInGoogleDrive() was called");
var fileMetadata = {
// auth: jwtClient, // Removed
name: "OfficService",
mimeType: "application/vnd.google-apps.folder",
parents: ['12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR'],
};
drive.files.create(
{
resource: fileMetadata,
fields: "id",
},
(err, file) => {
if (err) {
// Handle error
console.error(err);
} else {
console.log("***parent****" + file.data.id);
}
}
);
}
笔记:
- 在此修改中,它假设您已经能够使用 Drive API 和您的服务帐户获取和放置 Google Drive 的值。请注意这一点。
添加:
当您想检索您手动创建的文件的文件列表时,请修改范围如下。
从:
['https://www.googleapis.com/auth/drive.file'],
至:
['https://www.googleapis.com/auth/drive'],
关于范围
https://www.googleapis.com/auth/drive.file
,官方文档是这样说的。对应用程序创建或打开的文件的按文件访问。文件授权是按用户授予的,并在用户取消对应用程序的授权时撤销。
另外,如果您想只检索 的共享文件夹的文件列表12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR
,请进行如下修改。
从:
drive.files.list({
auth: jwtClient,
pageSize: 10,
fields: 'nextPageToken, files(id, name)',
}, (err, res) => {
至:
drive.files.list({
auth: jwtClient,
pageSize: 10,
fields: 'nextPageToken, files(id, name)',
q: "'12CCq1GGoTyDW_Ox09TZf5BDgaPAjB0AR' in parents", // Added
}, (err, res) => {
推荐阅读
- php - 受限制的 HTML 页面(使用 PHP)(安全吗?)
- yii2 - cKeditor 和 Elfinder 不会将文件加载到资产
- c# - 服务器不可用 503 - WebClient.DownloadData
- r - 将单词保存到数据框中
- vba - VBA 抛出错误中的颜色编码
- wordpress - 即将举行的活动的 Facebook 粉丝专页 .ics 链接不起作用
- vhdl - VHDL FSM 未编译
- maven - 使用 Maven for IntelliJ 将 Logger 实现设置为测试范围
- apache-spark - Spark Dataframe需要像RDD这样的过滤器后重新分区?
- websocket - 用于聊天应用程序的 Websocket 或 WebRTC?