从业二十年我见过数百起安全事件。其中最难解释的一类不是因为攻击手段高明而是因为防御者从一开始就站在了错误的战场上。一、故事从一个聪明的方案开始小明是一名全栈工程师工作认真代码整洁。他在 GitHub 上搭了一套 docsify 静态站点用来存放自己的私人 prompt 库、技术笔记、工作备忘。站点部署在 Cloudflare Pages 上访问速度极快。但有一个问题他不希望这些内容被外人看到。于是他想到了一个方案在index.html里加一段 JavaScript页面加载时弹出密码框用户输入密码后前端对其做 SHA256 哈希与硬编码在代码里的哈希值比对。匹配则放行不匹配则拒绝。script const CORRECT_HASH a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3; async function checkPassword() { const input document.getElementById(pwd).value; const hash await sha256(input); if (hash CORRECT_HASH) { document.getElementById(gate).style.display none; initDocsify(); } else { alert(密码错误); } } /script小明看着这段代码心里踏实了。SHA256 是工业级加密算法暴力破解要几亿年谁能破他把代码推送到 GitHub打开了公开仓库设置因为他想让 Cloudflare Pages 能自动拉取并部署。就在这一刻他以为的锁已经不存在了。二、三种绕过方式最慢的一种需要 30 秒小明的同事阿强知道这个站点随口问你那个笔记站真的加密了小明说SHA256很安全。阿强打开浏览器花了不到一分钟把小明的私人笔记完整读取了。他用了三种方法从最快到最慢方法一直接读原始文件10 秒docsify 是纯前端渲染所有内容都是.md文件。GitHub 公开仓库的每一个文件都可以通过raw.githubusercontent.com直接访问https://raw.githubusercontent.com/xiaoming/prompt-vault/main/prompts/private-notes.md不需要密码。不需要绕过任何 JS。不需要打开小明的站点。index.html那道门根本不在这条路上。小明锁了前门但所有窗户都是开着的。方法二DevTools 直接调用初始化函数15 秒即便阿强不知道文件路径他也可以打开小明的站点按 F12在 Console 里直接执行document.getElementById(gate).style.display none; initDocsify();密码框消失docsify 正常加载全部内容触手可及。JS 的运行环境是用户的浏览器用户对这个环境有完全控制权。任何运行在浏览器里的保护逻辑用户都可以修改、跳过、或者重放。这不是漏洞这是 Web 的基本架构。方法三查看源码破解哈希30 秒阿强在页面上右键 → 查看源代码直接看到const CORRECT_HASH a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3;他把这个哈希扔进 crackstation.net三秒钟明文密码出现了123。就算密码更复杂攻击者也可以用彩虹表、字典攻击或者直接在本地跑 hashcat。哈希是公开的时间只是问题。三、根本原因一个架构错误不是代码错误小明的问题不是密码太简单不是哈希算法选错了也不是 JS 写得不好。问题是他在错误的层做了鉴权。理解这一点需要分清三个层次初学者的认知我加了密码保护密码框存在用户需要输入密码。感觉安全。但感觉安全和实际安全之间有一道鸿沟。进阶者的认知哈希暴露了JS 可以被绕过原始文件是公开的这是技术层面的分析。三个绕过方式都清楚了。结论是客户端鉴权对于公开仓库里的内容无法提供任何实质保护。第一性原理的认知鉴权必须发生在资源被交付之前这才是根本。什么是鉴权鉴权的本质是在未经授权的情况下阻止资源被访问。注意这个时序阻止→资源被访问。客户端鉴权的时序是什么浏览器先下载了index.html下载了所有.md文件然后在本地运行 JS决定是否展示内容。资源已经到达用户设备了。鉴权在资源交付之后才运行。这不是鉴权这是展示控制而展示控制在用户有完全控制权的环境里毫无意义。用一个比喻这就像你建了一座没有墙的房子然后在门口挂了一把锁。锁是真的但没有墙的房子锁锁的是什么差之毫厘谬以千里。一个架构决策的错误把所有后续的努力都变成了无用功。四、真正的解法Cloudflare Zero Trust Access真正的解法不是换一个更强的哈希不是把密码藏得更深而是把鉴权移到网络边界。这正是Cloudflare Zero Trust Access做的事情。它的工作原理当用户请求你的站点时请求首先到达 Cloudflare 的边缘节点。Cloudflare Access 在这里拦截请求在任何内容被传输给用户之前要求用户完成身份验证。验证通过后Cloudflare 颁发一个加密的访问令牌JWT后续请求携带这个令牌Cloudflare 验证令牌有效后才将请求转发到你的 Cloudflare Pages 源站。整个过程中你的.md文件、index.html在身份验证完成之前从未离开 Cloudflare 的服务器。这才是真正的鉴权资源在被授权之前根本不可达。零信任模型零信任Zero Trust不只是一个产品名称它是一种安全哲学不信任任何客户端无论是内网还是外网每次请求都要验证身份而不是登录一次就信任鉴权在最靠近资源的地方执行而不是在最远的地方浏览器端与小明的方案相比小明的方案Cloudflare Access鉴权位置用户浏览器最远端Cloudflare 边缘节点资源入口能否绕过 JS可以DevTools 直接绕过不可以请求不到达源站原始文件可访问可以raw.githubusercontent.com不适用源站已切换密钥是否暴露是哈希在源码里否凭证在 Cloudflare 管理适合场景无本质上不安全个人/团队私有站点五、配置步骤30 分钟从零到安全前提条件域名已托管在 Cloudflare或将 Pages 绑定到自定义域名站点已部署到 Cloudflare Pages第一步开启 Zero Trust登录 Cloudflare Dashboard左侧菜单选择Zero Trust按提示完成团队名称设置免费套餐支持最多 50 个用户个人使用完全够用第二步创建 Access Application在 Zero Trust Dashboard进入Access → Applications点击Add an application选择Self-hosted填写配置Application namePrompt Vault随意Application domainyour-site.pages.dev或你的自定义域名Session Duration24h根据需要调整第三步设置访问策略在应用配置中进入Policies标签创建新策略Policy nameOwner AccessActionAllowRuleSelector 选EmailsValue 填入你的邮箱地址如youexample.org第四步选择认证方式 — 推荐 Email OTP在Login Methods里Cloudflare 支持多种方式Google OAuth、GitHub OAuth、Email OTP 等。对于个人使用强烈推荐 Email OTP不需要注册 OAuth 应用不依赖第三方Google、GitHub 账号状态流程简单访问站点 → 输入邮箱 → 收到 6 位验证码 → 输入 → 通过验证码有效期短几分钟安全性高配置路径Zero Trust Dashboard →Settings → Authentication → Login methods → Add new → One-time PIN第五步验证打开无痕浏览器窗口访问你的站点你会看到 Cloudflare Access 的登录页面而不是你的 docsify 内容输入你的邮箱收取验证码输入通过后正常访问站点此时未输入邮箱验证码的任何人包括直接请求你的 Pages 域名都会被 Cloudflare 拦截在外。六、一个值得记住的原则配置完成之后小明回头看了看自己之前的代码。那段 SHA256 校验逻辑现在完全可以删掉了。不是因为它有害而是因为它从来就没有起到任何保护作用。它保护的是一个已经完全暴露的资源。他想起了一句话鉴权是阻止未授权访问资源。如果资源在鉴权运行之前就已经可达那鉴权就已经失败了。这不是事后诸葛亮。这是第一性原理。零信任这个词初听起来像是营销语言。但它背后的逻辑很严谨不假设任何请求是安全的不因为在内网或上次验证通过了就信任每一次资源访问都要在最靠近资源的地方重新验证身份这和把密码哈希放在浏览器里的逻辑南辕北辙。一个是在资源入口设防一个是在资源已到达用户手中之后再锁门。七、现在就检查你的仓库读到这里请停下来做一件事打开你的 GitHub 仓库列表搜索这几个关键词password hash sha256 CORRECT_HASH checkPassword如果你的公开仓库里有这些字样你现在就面临和小明同样的处境。解法不复杂迁移到 Cloudflare Pages如果还没有开启 Cloudflare Zero Trust Access删掉那段 JS 鉴权代码——它不只是没用留着还会让你误以为自己是安全的最危险的状态不是完全没有保护而是**以为有保护实际上没有**。总结维度客户端哈希方案Cloudflare Zero Trust绕过难度极低10秒极高需控制 Cloudflare 账户实现复杂度低低30分钟配置完成维护成本低极低Cloudflare 托管真实安全性零生产级适合场景无个人/团队私有文档站安全的核心不是算法有多强而是架构是否正确。把 SHA256 换成 SHA512、Argon2在这个场景里毫无意义。因为问题从来不在算法在架构。把鉴权移到网络边界。其余的交给 Cloudflare。联系方式 Website: https://todzhang.com/ 微信公众号: 竹书纪年的IT男 Email: phray163.com