
google 表单原生不支持密码或白名单访问控制,但可通过 apps script 在提交后自动校验预设验证码,并即时屏蔽无效响应,实现“伪密码门禁”效果。本文详解实现逻辑、修复常见脚本错误,并提供健壮可部署的完整方案。
在实际调研场景中,常需确保仅授权人员(如内部员工、受邀嘉宾)可提交表单,而非公开开放。虽然 Google 表单本身不提供前端密码验证、IP 限制或实时白名单拦截功能(即无法在用户点击“提交”前阻止非法访问),但我们可以通过 Google Apps Script 的 onFormSubmit 触发器,在响应提交后的毫秒级时间内完成校验,并自动作废无效提交——这是一种被广泛验证、稳定可靠的“后置准入控制”方案。
✅ 正确实现逻辑与关键修复点
您原始脚本存在多个关键问题,导致无法正常工作:
- ❌ e.response 在 onFormSubmit 触发器中不可用(该事件对象仅含 e.values, e.namedValues, e.source, e.authMode 等字段,不包含响应实例);
- ❌ form.setAcceptingResponses(false) 会全局关闭整个表单,影响所有用户,而非仅拒绝当前提交;
- ❌ 未处理空值、大小写敏感、首尾空格等常见校验陷阱;
- ❌ 缺少错误日志与幂等保护,易因重复触发导致误关表单。
以下是修复后的生产就绪版脚本:
function onFormSubmit(e) {
// 1. 获取表单和响应数据
const form = FormApp.getActiveForm();
const namedValues = e.namedValues; // { "验证码": ["ABC123"], "姓名": ["张三"] }
// 2. 提取验证码(假设题目标签为"验证码",请按实际修改)
const codeInput = (namedValues["验证码"] || [null])[0];
if (!codeInput || typeof codeInput !== 'string') {
console.warn("⚠️ 未检测到有效验证码字段,跳过校验");
return;
}
const submittedCode = codeInput.trim().toUpperCase(); // 统一转大写并去空格
// 3. 读取白名单代码(推荐:使用缓存 + 防错读取)
const sheetUrl = 'YOUR_GOOGLE_SHEET_URL'; // 替换为您的表格链接
try {
const ss = SpreadsheetApp.openByUrl(sheetUrl);
const codeSheet = ss.getSheetByName('Sheet1') || ss.getSheets()[0];
const codeRange = codeSheet.getRange('A2:A'); // 建议从 A2 开始(A1 为标题),避免空行干扰
const codes = codeRange.getValues()
.flat()
.filter(String) // 移除空单元格
.map(c => String(c).trim().toUpperCase());
// 4. 校验通过则保留,否则标记为“已拒绝”并隐藏响应
if (!codes.includes(submittedCode)) {
// ⚠️ 关键:不关闭表单!而是删除/归档该响应
const responseId = e.responseId;
const allResponses = form.getResponses();
const targetResponse = allResponses.find(r => r.getId() === responseId);
if (targetResponse) {
form.deleteResponse(responseId); // 彻底移除无效响应(不可恢复)
console.info(`✅ 已删除非法提交(ID: ${responseId},验证码: ${submittedCode})`);
}
return;
}
console.info(`✅ 验证码校验通过: ${submittedCode}`);
} catch (err) {
console.error("❌ 白名单读取失败:", err.toString());
// 可选:发送告警邮件或记录到日志表
}
}? 部署步骤(务必按顺序操作)
- 在您的 Google 表单中 → 点击右上角「⁝」→ 「编辑表单脚本」(将打开 Apps Script 编辑器);
- 粘贴上方脚本,将 YOUR_GOOGLE_SHEET_URL 替换为您存放验证码的 Sheet 链接;
- 确认验证码题目标签名:脚本中 namedValues["验证码"] 的 "验证码" 必须与表单中该题目的精确标题文字一致(区分中英文标点);
-
保存项目 → 点击左上角「部署」→ 「新建部署」→ 选择触发器类型为:
▶️ onFormSubmit(事件类型:From form → On form submit); - 授权运行权限(首次部署时需授权 https://www.googleapis.com/auth/forms.currentonly 和 https://www.googleapis.com/auth/spreadsheets.readonly)。
⚠️ 重要注意事项
- 隐私与合规:被删除的响应无法恢复,且不会出现在任何导出文件中,符合 GDPR/《个人信息保护法》对“无效数据及时清除”的要求;
- 性能优化:白名单建议控制在 5,000 行以内;若代码量极大,可改用 PropertiesService 缓存校验集(减少 Sheet I/O);
- 防暴力尝试:Google 表单本身无频率限制,如需增强防护,可在 Sheet 中添加“使用次数”列,配合脚本实现一次性验证码;
-
替代方案对比:
- ✅ 推荐:本方案零第三方依赖、完全可控、免费;
- ⚠️ 插件/外链工具(如 FormLimiter)仅能限提交次数或时间,无法做白名单校验;
- ❌ 不推荐用“隐藏题+跳转逻辑”伪装密码——前端可被审查元素绕过,毫无安全性。
通过以上配置,您即可在不改变表单外观的前提下,构建一道轻量、可靠、合规的访问防线。所有未持有效验证码的提交将被静默丢弃,而合法用户全程无感知——这才是面向生产环境的专业实践。










