Google Apps Script Web应用权限限制问题及Spreadsheet安全编辑方案咨询
问题:限制Spreadsheet编辑权限并允许内部用户通过表单提交修改
背景:许多企业将Spreadsheet Service(简称"SS")用作应用数据库,但防护意识不足,给所有员工开放SS编辑权限,存在用户误操作(如插入列)修改SS的风险。
需求:不使用付费的AppSheet,降低SS误编辑风险。具体要求:普通用户无法直接编辑SS,但可通过绑定SS的GAS打开表单提交信息来修改SS内容。
已尝试方案:
- 设置仅所有者可编辑SS;
- 准备独立于SS的独立脚本Web应用(执行者为所有者,访问权限设为"组织内人员"),代码如下:
function doPost(e) { const SS = SpreadsheetApp.openById('*************************************'); const SHEET = SS.getSheetByName('sheetname'); SHEET.getRange('A1').setValue(e.parameter.text); }
- 给SS绑定脚本,准备增删改表单并向Web应用发送POST请求,代码如下:
[code.gs]
[form.html]const SS = SpreadsheetApp.getActiveSpreadsheet(); const APP_URL = "--the endpoint of doPost function--"; function onOpen(e) { SS.addMenu( 'Menu', [{name : 'showForm', functionName : 'showForm'}] ); } function showForm(){ const html = HtmlService.createHtmlOutputFromFile('form'); SpreadsheetApp.getUi().showModalDialog(html, 'Title'); } function processForm(formObject) { const text = formObject.text; const params = { 'method': 'post', 'payload' : { 'text': text }, 'muteHttpExceptions': true } UrlFetchApp.fetch(APP_URL, params); }<!DOCTYPE html> <html> <head> <base target="_top"> <script> // Prevent forms from submitting. function preventFormSubmit() { var forms = document.querySelectorAll('form'); for (var i = 0; i < forms.length; i++) { forms[i].addEventListener('submit', function(event) { event.preventDefault(); }); } } window.addEventListener('load', preventFormSubmit); function handleFormSubmit(formObject) { google.script.run.withSuccessHandler(onSuccess).processForm(formObject); } function onSuccess(){ google.script.host.close(); } </script> </head> <body> <form id="myForm" onsubmit="handleFormSubmit(this)"> <input name="text" type="text" /> <input type="submit" value="Submit" /> </form> </body> </html>
遇到问题:因Web App访问权限限制为"组织内人员",GAS发起的请求被拒绝,但为安全起见不能将权限设为"所有人"。
咨询:如何让doPost函数识别用户属于组织内?或有无其他实现需求的方案?
解决方案
方案一:让Web App验证组织内用户身份
在绑定SS的脚本请求中携带用户OAuth令牌,同时在Web App中验证用户所属域名:
- 修改绑定SS的
processForm函数,添加身份凭证:
function processForm(formObject) { const text = formObject.text; // 获取当前用户的OAuth令牌 const token = ScriptApp.getOAuthToken(); const params = { 'method': 'post', 'payload' : { 'text': text }, 'headers': { 'Authorization': 'Bearer ' + token }, 'muteHttpExceptions': true } UrlFetchApp.fetch(APP_URL, params); }
- 修改独立Web App的
doPost函数,验证用户域名:
function doPost(e) { const user = Session.getActiveUser(); const domain = user.getDomain(); // 替换为你的企业域名 if (domain !== 'your-company-domain.com') { return ContentService.createTextOutput('Unauthorized').setStatusCode(401); } const SS = SpreadsheetApp.openById('*************************************'); const SHEET = SS.getSheetByName('sheetname'); SHEET.getRange('A1').setValue(e.parameter.text); return ContentService.createTextOutput('Success').setStatusCode(200); }
注意:部署Web App时,执行权限选择"以访问者身份执行",这样才能获取到发起请求的用户身份,访问权限保持"组织内人员"。
方案二:简化架构,无需独立Web App
直接在绑定SS的脚本中实现修改逻辑,规避跨脚本权限问题:
- 保持SS权限为"仅所有者可编辑";
- 修改绑定SS的脚本,删除外部Web App调用,直接操作SS:
const SS = SpreadsheetApp.getActiveSpreadsheet(); function onOpen(e) { SS.addMenu( 'Menu', [{name : 'showForm', functionName : 'showForm'}] ); } function showForm(){ const html = HtmlService.createHtmlOutputFromFile('form'); SpreadsheetApp.getUi().showModalDialog(html, 'Title'); } function processForm(formObject) { const text = formObject.text; const SHEET = SS.getSheetByName('sheetname'); // 以脚本所有者权限执行修改 SHEET.getRange('A1').setValue(text); }
此方案中,脚本默认以所有者身份执行,普通用户触发表单提交时,会通过所有者权限修改SS,自身无需直接编辑权限,更简洁安全。
内容的提问来源于stack exchange,提问作者user16784320
相关产品推荐
相关产品推荐

