我遇到了与这里描述的相同的问题:谷歌网络应用程序-获取用户电子邮件,但作为所有者运行脚本
给定的解决方案是创建一个以当前用户身份运行的客户端脚本和一个以所有者身份运行的中间件脚本。然后客户端脚本用UrlFetchApp.fetch(...)
调用中间件脚本,中间件在doGet(e)
函数中处理请求。这在测试环境中运行良好。
但为了使其高效,我需要只有域用户才能访问中间件脚本。然后,UrlFetchApp.fetch
调用返回一个登录对话框。
那么,有没有一种方法可以在不手动登录的情况下通过URL调用谷歌应用程序脚本?
这是我使用用户权限运行的前端脚本:
function doGet(e) {
var data = HtmlService.createHtmlOutput(backendCall());
// TODO: Format data as HTML
return HtmlService.createHtmlOutput(data);
}
function backendCall() {
const url = `${backendUrl}?user=${encodeURI(Session.getEffectiveUser().getEmail())}`;
const options = {
method: 'GET',
muteHttpExceptions: true,
headers: {
Authorization: `Bearer ${ScriptApp.getOAuthToken()}`,
Accept: 'application/json'
}
};
return UrlFetchApp.fetch(url, options).getContentText();
}
以及使用所有者权限运行的后端脚本:
function doGet(e) {
return ContentService.createTextOutput(getUserData(e.parameter.user)).setMimeType(ContentService.MimeType.JSON);
}
function getUserData(user) {
const sheet = SpreadsheetApp.openById(sheetId).getActiveSheet();
const data = sheet.getDataRange().getValues() // Get whole sheet data. This is much faster than getting data row by row.
.filter((row) => row[cols.user] === user) // Select data for selected user.
.map(formatRow) // Format sheet row to JavaScript objects.
.sort((a, b) => a.day - b.day); // Sort by date.
return JSON.stringify(data); // Return as JSON string.
}
结果是,后端脚本返回的不是数据,而是错误消息";错误401未经授权";。
我复制了您的代码并进行了一些修改以使其工作:
对于两个项目:
- 转到"设置",并将
display manifest "appsscript.json"
选为ON - 使用
oauthScopes
修改您的appscript.json,如下所示:
{
"timeZone": "Europe/Paris",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"webapp": {
"executeAs": "USER_DEPLOYING",
"access": "DOMAIN"
},
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/userinfo.email"
]
}
您的前端项目:
const backendUrl = "https://script.google.com/.../exec";
function doGet(e) {
return ContentService.createTextOutput(backendCall());
//instead of : HtmlService.createHtmlOutput
}
function backendCall() {
const url = `${backendUrl}?user=${encodeURI(Session.getEffectiveUser().getEmail())}`;
const options = {
method: 'GET',
muteHttpExceptions: true,
headers: {
Authorization: `Bearer ${ScriptApp.getOAuthToken()}`
}
};
return UrlFetchApp.fetch(url, options).getContentText();
}
后端项目:
function doGet(e) {
return ContentService.createTextOutput(getUserData(e.parameter.user)).setMimeType(ContentService.MimeType.JSON);
}
function getUserData(user) {
const sheet = SpreadsheetApp.openById([ID_SPREADSHEET]).getSheetByName([SHEETNAME]);
//instead of getActiveSheet()
const data = sheet.getDataRange().getValues()
.filter((row) => row[cols.user] === user)
.map(formatRow)
.sort((a, b) => a.day - b.day);
return JSON.stringify(data);
}