[英]POST data to Google Sheet web app from AWS Lambda
CURRENTLY目前
I have a Google Sheets App Script 'web app'我有一个 Google 表格应用脚本“网络应用”
Script in Goolge Sheets Goolge 表格中的脚本
function doPost(e) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Sheet1");
sheet.getRange("A1").setValue("Hello!")
return "Success!"
}
Google Apps Script Web App Config: Google Apps 脚本 Web 应用配置:
Execute as: Me // or as User. I've tried both.
Who has access: Anyone within MyOrganisation
I want to make a POST request to the above Web App from AWS Lambda.我想从 AWS Lambda 向上述 Web 应用程序发出 POST 请求。
AWS Lambda.js: AWS Lambda.js:
const { GoogleSpreadsheet } = require("google-spreadsheet");
const doc = new GoogleSpreadsheet(
{spreadsheetId}
);
await doc.useServiceAccountAuth({
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, "\n"),
});
let token = doc["jwtClient"]["credentials"]["access_token"];
await new Promise((resolve, reject) => {
const options = {
host: 'script.google.com',
path: "/macros/s/{myscriptid}/exec", //<-- my web app path!
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer "+ token
}
};
//create the request object with the callback with the result
const req = HTTPS.request(options, (res) => {
resolve(JSON.stringify(res.statusCode));
});
// handle the possible errors
req.on('error', (e) => {
reject(e.message);
});
//do the request
req.write(JSON.stringify(data));
//finish the request
req.end();
});
console.log("response:"+JSON.stringify(response))
GCP Service Account GCP 服务帐号
EDIT
access to the Google Sheet with the doPost(e)
script.此服务帐户具有使用doPost(e)
脚本对 Google 工作表的EDIT
访问权限。Token Output:令牌 Output:
"jwtClient": {
"_events": {},
"_eventsCount": 0,
"transporter": {},
"credentials": {
"access_token": "somelongvalue...............", //<-- what I use
"token_type": "Bearer",
"expiry_date": 1661662492000,
"refresh_token": "jwt-placeholder"
},
"certificateCache": {},
"certificateExpiry": null,
"certificateCacheFormat": "PEM",
"refreshTokenPromises": {},
"eagerRefreshThresholdMillis": 300000,
"forceRefreshOnFailure": false,
"email": "serviceaccount@appspot.gserviceaccount.com",
"key": "-----BEGIN PRIVATE KEY-----\nsomelongvalue=\n-----END PRIVATE KEY-----\n",
"scopes": [
"https://www.googleapis.com/auth/spreadsheets"
],
"subject": null,
"gtoken": {
"key": "-----BEGIN PRIVATE KEY-----\nsomelongvalue=\n-----END PRIVATE KEY-----\n",
"rawToken": {
"access_token": "somelongvalue...............",
"expires_in": 3599,
"token_type": "Bearer"
},
"iss": "serviceaccount@appspot.gserviceaccount.com",
"sub": null,
"scope": "https://www.googleapis.com/auth/spreadsheets",
"expiresAt": 1661662492000
}
}
ISSUE问题
Current response:目前的回应:
response:"401"
MyOrganisation
, I struggle to find a way to authenticate my POST request.当 Web 应用程序对“任何人”开放时,它运行良好,但是一旦我限制为MyOrganisation
,我就很难找到一种方法来验证我的 POST 请求。HELP!帮助!
How do I set up a POST request to my Google Sheets web app such that it can be protected by authentication?如何设置对我的 Google 表格 web 应用程序的 POST 请求,以便可以通过身份验证对其进行保护? Right now, I'd be happy to find ANY means to authenticate this request (not necessarily a service account) that doesn't leave it completed open to public.现在,我很高兴找到任何方法来验证这个请求(不一定是服务帐户),而不是让它完成对公众开放。
Should I use this hack?我应该使用这个黑客吗?
One idea I had was to put a "secret" into my lambda function, and then make the web app public.我的一个想法是将“秘密”放入我的 lambda function 中,然后公开 web 应用程序。 The web app would check the secret, if if matched, would execute the function. web 应用程序将检查密钥,如果匹配,将执行 function。
In order to access Web Apps using the access token with a script, the scopes of Drive API are required to be included.为了使用带有脚本的访问令牌访问 Web 应用程序,需要包含 Drive API 的范围。 Those are https://www.googleapis.com/auth/drive.readonly
, https://www.googleapis.com/auth/drive
, and so on.这些是https://www.googleapis.com/auth/drive.readonly
、 https://www.googleapis.com/auth/drive
等等。 Ref 参考
When I saw your showing script, it seems that the access token is retrieved using google-spreadsheet
.当我看到您的显示脚本时,似乎使用google-spreadsheet
检索了访问令牌。 When I saw the script of google-spreadsheet
, it seems that this uses only the scope of https://www.googleapis.com/auth/spreadsheets
.当我看到google-spreadsheet
的脚本时,似乎这只使用了https://www.googleapis.com/auth/spreadsheets
的 scope 。 Ref 参考
From this situation, I thought that the reason for your current issue might be due to this.从这种情况来看,我认为您当前问题的原因可能是由于此。 If my understanding is correct, how about the following modification?如果我的理解是正确的,那么下面的修改呢? In this modification, the access token is retrieved by googleapis for Node.js from the service account.在此修改中,访问令牌由 googleapis 从服务帐户中检索到 Node.js。 Ref参考
function doPost(e) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Sheet1");
sheet.getRange("A1").setValue("Hello!")
return ContentService.createTextOutput("Success!"); // Modified
}
const { google } = require("googleapis");
const HTTPS = require("https");
const auth = new google.auth.JWT(
"###", // Please set client_email here.
null,
"###", // Please set private_key here. When you set private_key of service account, please include \n.
["https://www.googleapis.com/auth/drive.readonly"],
null
);
function req(token) {
return new Promise((resolve, reject) => {
const data = { key1: "value1" }; // Please set your value.
const options = {
host: "script.google.com",
path: "/macros/s/{myscriptid}/exec", //<-- my web app path!
method: "POST",
headers: {Authorization: "Bearer " + token},
};
const req = HTTPS.request(options, (res) => {
if (res.statusCode == 302) {
HTTPS.get(res.headers.location, (res) => {
if (res.statusCode == 200) {
res.setEncoding("utf8");
res.on("data", (r) => resolve(r));
}
});
} else {
res.setEncoding("utf8");
res.on("data", (r) => resolve(r));
}
});
req.on("error", (e) => reject(e.message));
req.write(JSON.stringify(data));
req.end();
});
}
auth.getAccessToken().then(({ token }) => {
req(token).then((e) => console.log(e)).catch((e) => console.log(e));
});
Success!
运行此脚本时,当 Web Apps 正确部署后,Web Apps 的脚本运行Success!
is returned.被退回。If this modified script was not useful for your Web Apps setting, please test as follows.如果此修改后的脚本对您的 Web 应用程序设置没有用,请进行如下测试。
When you set private_key
of service account, please include \n
.当您设置服务帐户的private_key
时,请包含\n
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.