Google Sheets Add-on共享后custom functions执行及API密钥归属问题咨询
解决Google Sheets Add-on自定义函数共享权限与API Key隔离问题
问题根源分析
- 未安装插件用户可执行自定义函数并使用原用户API Key:Google Sheets自定义函数默认以函数创建者身份运行,即使表格被共享,未安装插件的用户调用函数时,仍会使用原用户的授权上下文(包括
User Properties中的API Key)。 - 已安装插件用户侧边栏无法读取自身API Key:
PropertiesService.getUserProperties()是用户级别的存储,每个用户的属性完全独立,原用户的API Key不会同步到共享用户的属性中,因此新用户打开侧边栏时读取的是空值。
解决方案
一、限制未安装插件用户执行自定义函数
在自定义函数开头添加授权状态验证,未安装/未授权插件的用户无法通过验证,会返回明确错误提示:
/** * @OnlyCurrentDoc * 获取Similarweb网站数据 * @param {string} url 目标网址 * @return {object} 网站分析数据 * @customfunction */ function GET_SIMILARWEB_DATA(url) { // 验证用户是否已授权插件(未安装插件无法通过此验证) const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); if (authInfo.getAuthorizationStatus() !== ScriptApp.AuthorizationStatus.REQUIRED) { return "⚠️ 请先安装并授权《The Official Similarweb For Google Sheets™》插件"; } // 后续逻辑... }
@OnlyCurrentDoc注释限制插件权限仅作用于当前文档,降低用户授权门槛;- 未安装插件的用户无法获取插件的授权权限,验证失败后无法执行后续API调用逻辑。
二、确保自定义函数调用当前用户的API Key
核心是改变自定义函数的运行身份,让其以当前执行用户的身份运行,从而读取自身的User Properties:
- 完善自定义函数的身份验证与API Key读取逻辑:
function GET_SIMILARWEB_DATA(url) { // 授权验证(同上) const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); if (authInfo.getAuthorizationStatus() !== ScriptApp.AuthorizationStatus.REQUIRED) { return "⚠️ 请先安装并授权插件"; } // 读取当前用户的API Key const userProps = PropertiesService.getUserProperties(); const apiKey = userProps.getProperty('SIMILARWEB_API_KEY'); if (!apiKey) { return "⚠️ 请先在插件侧边栏设置你的API Key"; } // 调用Similarweb API并返回结果 const apiResponse = UrlFetchApp.fetch(`https://api.similarweb.com/v1/...?key=${apiKey}&url=${url}`); return JSON.parse(apiResponse.getContentText()); }
- 插件安装与侧边栏逻辑优化:
添加onInstall触发器确保用户首次安装时初始化自身属性,同时侧边栏只读取当前用户的API Key:
// 插件安装时触发 function onInstall(e) { onOpen(e); // 初始化当前用户的API Key属性(避免空值报错) const userProps = PropertiesService.getUserProperties(); if (!userProps.getProperty('SIMILARWEB_API_KEY')) { userProps.setProperty('SIMILARWEB_API_KEY', ''); } } // 打开表格时添加插件菜单 function onOpen(e) { SpreadsheetApp.getUi() .createMenu('Similarweb') .addItem('打开API设置', 'showSidebar') .addToUi(); } // 显示侧边栏 function showSidebar() { const html = HtmlService.createHtmlOutputFromFile('sidebar') .setTitle('Similarweb API 设置'); SpreadsheetApp.getUi().showSidebar(html); } // 侧边栏调用:读取当前用户API Key function getUserApiKey() { const userProps = PropertiesService.getUserProperties(); return userProps.getProperty('SIMILARWEB_API_KEY') || ''; } // 侧边栏调用:保存当前用户API Key function saveUserApiKey(key) { const userProps = PropertiesService.getUserProperties(); userProps.setProperty('SIMILARWEB_API_KEY', key.trim()); }
侧边栏HTML示例(仅读取当前用户数据):
<script> window.onload = () => { // 加载当前用户的API Key google.script.run.withSuccessHandler(key => { document.getElementById('apiKey').value = key; }).getUserApiKey(); }; function saveKey() { const key = document.getElementById('apiKey').value; google.script.run.withSuccessHandler(() => { alert('API Key已保存'); }).saveUserApiKey(key); } </script> <div style="padding: 1rem;"> <input type="text" id="apiKey" placeholder="输入你的Similarweb API Key" style="width: 100%; padding: 0.5rem;"> <button onclick="saveKey()" style="margin-top: 1rem; padding: 0.5rem 1rem;">保存</button> </div>
关键注意事项
- 用户首次运行自定义函数时会弹出授权提示,需引导用户完成授权(可通过插件菜单触发授权流程,降低用户操作门槛);
User Properties完全隔离,不会跨用户共享数据,确保每个用户的API Key仅自己可见和使用;- 未安装插件的用户无法通过授权验证,自然无法执行自定义函数,彻底解决权限泄漏问题。
内容的提问来源于stack exchange,提问作者Sankar Chinnakotla
相关产品推荐
相关产品推荐

