javascript - 如何使用服务帐户和 Google Drive API 解决 403 错误
问题描述
我正在尝试编写一个客户端 JS 脚本,该脚本将从我的 gDrive 获取图像以使用服务帐户显示在网站上。我创建了服务帐户,并为该项目添加并启用了 google Drive API。但是当我运行脚本时,我收到了 403 错误:已超出未经身份验证使用的每日限制。继续使用需要注册。我认为这可能与权限或范围有关?我查看了其他几个堆栈溢出,但似乎无法弄清楚。
Google Drive 服务帐号返回 403 usageLimits
其中一些提到添加角色或范围,但我不知道如何添加它们或我需要添加哪些。GSuite 帐户是强制性的吗?听起来我需要进入 GSuite 管理控制台来添加范围?我不想注册一个帐户,因为它不是免费的。任何帮助,将不胜感激。我的代码如下所示:
function gDrive() {
function init(callback) {
authorizeClient(getJWT()).then(function(token) {
loadClient(token, callback);
});
}
/* Retrieve a signed JWT */
function getJWT() {
// Prepare header, payload, and key
let oHeader = {
"alg": "RS256",
"typ": "JWT"
};
let sHeader = JSON.stringify(oHeader);
let oPayload = {
"iss": "SERVICE ACCOUNT EMAIL",
"sub": "SERVICE ACCOUNT EMAIL",
"aud": "https://www.googleapis.com/oauth2/v3/token",
"iat": KJUR.jws.IntDate.getNow(),
"exp": KJUR.jws.IntDate.get("now + 1hour"),
"scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.readonly"
};
let sPayload = JSON.stringify(oPayload);
let privKey = "-----BEGIN PRIVATE KEY-----BLAH BLAH BLAH\n-----END PRIVATE KEY-----\n";
// Sign JWT
return signedJWS = KJUR.jws.JWS.sign(null, sHeader, sPayload, privKey);
}
/* Http POST to Google Auth api */
function authorizeClient(JWS) {
// Request access token
const url = "https://www.googleapis.com/oauth2/v3/token";
let encodedData = "";
let encodedDataPairs = [];
encodedDataPairs.push(encodeURIComponent("grant_type") + '=' + encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"));
encodedDataPairs.push(encodeURIComponent("assertion") + '=' + encodeURIComponent(JWS));
encodedData = encodedDataPairs.join('&').replace(/%20/g, '+');
const params = {
headers: {"content-type":"application/x-www-form-urlencoded"},
body: encodedData,
method: "POST"
};
return fetch(url, params).then(accessTokenSucces).then(returnToken).catch(accessTokenFailed);
}
function accessTokenSucces(data) {
console.log("Retrieved access token");
return data.json();
}
function returnToken(resp) {
return resp.access_token;
}
function accessTokenFailed(error) {
console.log("Requesting access token failed: " + error);
}
function loadClient(accessToken, callback) {
gapi.load('client', function() {
console.log("loading client");
gapi.client.setToken(accessToken);
console.log("set access token");
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/drive/v3/rest").then(clientLoadSuccessful).then(callback).catch(clientLoadFailed);
})
}
function clientLoadSuccessful() {
console.log("Client loaded");
return Promise.resolve();
}
function clientLoadFailed(error) {
console.log("Loading Client failed: " + error);
return Promise.reject();
}
function fetchAllImages(fileName, chapter, callback) {
console.log("fetching images");
let initialRequest = gapi.client.drive.files.list({"q": "mimeType contains \"image\" and name contains '"
+ fileName + "_ch" + chapter + "'"});
retrievePageOfFiles(initialRequest, [], fileName, chapter);
function retrievePageOfFiles(request, result) {
request.execute(function(resp) {
result = result.concat(resp.files);
let nextPageToken = resp.nextPageToken;
if (nextPageToken) {
request = gapi.client.drive.files.list({
"pageToken": nextPageToken,
"q": "mimeType contains \"image\" and name contains '" + fileName + "_ch" + chapter + "'"
});
retrievePageOfFiles(request, result);
} else {
console.log("Images retrieved");
callback(result);
}
}).catch(function(err) {
console.log("Could not retrieve images: " + err);
});
}
}
return {
init: init,
fetchAllImages: fetchAllImages
};
}
gDrive().init(runApp);
function runApp() {
console.log("Running App");
gDrive().fetchAllImages("FILENAME", "1", imageCallback);
}
function imageCallback(data) {
console.log("Images Retrieved!");
console.log(data);
}
解决方案
- 运行脚本时,
Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.
会发生错误。 - 您想删除此错误。
如果我的理解是正确的,那么这个修改呢?我认为可以使用通过您的脚本检索到的访问令牌。因此,请按如下方式修改您的脚本。
从:
gapi.client.setToken(accessToken);
至:
gapi.client.setToken({access_token: accessToken});
参考:
如果这不是您问题的直接解决方案,我深表歉意。
推荐阅读
- c# - 无法将用 C++ 编写的 Dll 导入 C# .NetCore
- android - 应用程序:compileDebugJavaWithJavac 错误。java.io.IOException:文件名、目录名或卷标语法不正确
- python - 如何使用 Telethon 加入 Telegram 中的多个频道?
- r - 如何使用 group_by 对所有不是字符/因素的变量求和?
- java - 休眠分离实体被传递以保持
- windows-subsystem-for-linux - 如何将 wsl 命令行参数添加到 Windows 终端配置?
- c++ - 'double' 和 'int' 类型的无效操作数到二进制 'operator%'
- bash - 在 bash 中包装 sudo 和 ssh 命令
- javascript - 如何在javascript中将日期作为不带双引号的参数传递
- reactjs - 带有情感/风格的快照测试 className