单文件 Cloudflare Worker:无前端构建、无数据库、无外部依赖,一个 worker.js 加一个 KV 即可运行。
- 双栏编辑器:笔记 / 小说(多卷多章)两种类型;记事本默认「对照」模式,编辑与预览并排、随输入实时刷新;标题/正文搜索(命中高亮、匹配计数、Esc 清空、Ctrl+K 聚焦)、字数统计;手机端抽屉式作品列表。
- 随手记管理:每篇显示创建 / 修改时间;列表上方工具行可切换排序,默认按修改时间,可选创建时间、标题或手动排序(置顶优先,拖拽或 ↑↓ 微调);批量管理支持全选 / 清空 / 反选(作用于当前搜索结果)、批量置顶、按列表顺序合并为新笔记、导出
.md与批量删除。 - Markdown:标题、加粗、引用、列表、任务清单、代码块、链接、GFM 表格(1~12 列 × 1~50 行);导出
.md。预览只读渲染,不改动保存的原文;不支持外部图片与任意 HTML。 - 沉浸阅读:自动跟随当前主题配色(暖纸→纸张、松影→夜间、陶土→护眼),也可手动切换纸张/护眼/夜间。
- 版本历史:云端自动留存最近 10 份快照,按当前打开的文章独立展示实际变化的版本,回滚仅作用于该文章;回滚前当前内容先自动留存,可再回滚撤销。
- 安全基线:私人入口 + HMAC 会话 + 登录限流 + CSRF/SSRF 防护 + DOMPurify 过滤,详情见架构与安全。
部署后的访问入口与登录凭据由以下两项配置决定:
| 用途 | 配置项 | 说明 |
|---|---|---|
| 登录页面地址 | Secret login |
填写入口后缀(如 my-notes),登录页地址即为 https://<Worker名>.<账户子域>.workers.dev/my-notes;仅填写路径,不含域名;取值为 3~128 位英文字母、数字、下划线或连字符。 |
| 登录密码校验依据 | Secret PASSWORD_HASH(配合 PASSWORD_SALT) |
两种填写方式:① 按本文「日常操作 → 改密码」中的公式计算 32 位十六进制加盐 MD5(推荐);② 直接填写密码原文,由后端在登录时计算加盐 MD5 并比对(原文仅保存于 Cloudflare Secrets)。 |
即:login 指定登录页面的访问地址,PASSWORD_HASH 指定登录时的密码校验依据。
其余配置:
| 名称 | 类型 | 作用 |
|---|---|---|
PASSWORD_SALT |
Secret | 密码验证的盐,任意非空字符串(建议 64 位随机十六进制) |
SESSION_SECRET |
Secret | 会话 Cookie 签名密钥,任意非空字符串(建议 64 位随机十六进制);更换后所有登录状态失效 |
PROXY_ALLOWED_HOSTS |
普通变量 | 采集代理的域名白名单,逗号分隔、精确匹配;留空禁用网络采集 |
三个 Secret 字段(PASSWORD_SALT / PASSWORD_HASH / SESSION_SECRET)都无格式强制、兼容明文,首尾空格和换行自动忽略;但短盐/短密钥会降低防破解强度,正式使用建议随机长值。login 无效或未设置时关闭私人入口。
- 本目录运行
npm install --save-dev wrangler,再运行npx wrangler login登录 Cloudflare。 - 修改
wrangler.jsonc的name为目标 Worker 名称,将 KV ID 替换为目标 namespace ID。升级已有项目必须使用原来的 KV 才能读到已有数据(数据键user_creative_data);新项目运行npx wrangler kv namespace create CLOUD_EDITOR_KV。 - PowerShell 运行
./scripts/setup-secrets.ps1,按隐藏输入提示设置密码,生成.dev.vars和secrets.json(均在忽略列表中,不会提交)。 - 如使用小说采集,在
PROXY_ALLOWED_HOSTS填入可信公网域名(重定向域名也要列入);留空禁用网络采集,离线 HTML 采集仍可用。 - 检查限流
namespace_id未被账号内其他应用占用;默认每 IP、每 Cloudflare 节点每分钟最多 5 次登录。 npm test通过后运行npx wrangler deploy --secrets-file secrets.json,代码与 Secrets 一并发布。- 打开部署输出的
https://<地址>/<login>验证:登录、保存、刷新恢复、历史回滚;未登录请求/<login>/api/get-data应返回 401。
-
创建 Worker 并粘贴代码:Workers & Pages → Create → Create Worker,名称如
note;在线编辑器清空模板,粘贴worker.js全部内容,Deploy。 -
创建 KV:Storage & Databases → KV → Create namespace(如
note-data)。升级旧项目必须选择原来的 namespace。 -
绑定 KV:Worker → Settings → Bindings → Add → KV namespace,变量名称填
CLOUD_EDITOR_KV,选择上一步的 namespace。 -
绑定登录限流(必需):同页 Add → Rate limiting,变量名称
LOGIN_RATE_LIMITER,namespace ID 填账号内未占用的正整数(如1001),限制 5 次 / 60 秒。跳过将无法登录;若绑定列表没有 Rate limiting 类型,只能用命令行方式。 -
添加 Secrets:Settings → Variables and Secrets → Add,类型选 Secret:
名称 填写内容 对应作用 login入口后缀,如 my-notes登录页网址: https://…/<login>PASSWORD_SALT任意非空字符串,建议随机十六进制(生成命令见下) 密码验证的盐 PASSWORD_HASH直接填登录密码原文,或按「日常操作 → 改密码」公式计算哈希 登录页要输入的密码 SESSION_SECRET任意非空字符串,建议随机十六进制 会话签名,更换后全部会话失效 # 生成 64 位随机十六进制(PASSWORD_SALT / SESSION_SECRET 都用它) (1..64 | ForEach-Object { '{0:x}' -f (Get-Random -Max 16) }) -join ''
-
添加普通变量(可选):同页 Add,类型 Text,名称
PROXY_ALLOWED_HOSTS,值为逗号分隔的可信采集域名。 -
验证:打开
https://<Worker 名称>.<账户子域>.workers.dev/<login>,依次验证登录、保存、刷新恢复、历史回滚。
以后更新:在线编辑器里重新粘贴新的 worker.js 保存即可,Secrets 和绑定不受影响。
登录时若提示「服务配置不完整,缺少:…」,冒号后面就是要补的清单——逐项到 Settings → Bindings / Variables and Secrets 里补齐即可,补完立即生效,无需重新部署。
改密码——三种做法任选:
-
最简单:把新密码原文直接填入
PASSWORD_HASHSecret,立即生效(原文会保存在 Cloudflare Secrets 中)。 -
更严谨:PowerShell 计算加盐哈希后覆盖
PASSWORD_HASH(明文不落任何存储):$salt = '粘贴现有 PASSWORD_SALT'; $pwd = Read-Host '新密码' [BitConverter]::ToString([Security.Cryptography.MD5]::Create().ComputeHash([Text.Encoding]::UTF8.GetBytes("${salt}:${pwd}"))).Replace('-','').ToLowerInvariant()
-
最彻底:重新运行
./scripts/setup-secrets.ps1,同时更换盐、SESSION_SECRET和哈希(KV 数据不受影响),再npx wrangler deploy --secrets-file secrets.json。
以上操作都会使旧会话失效,需重新登录。
改入口:修改 login Secret。旧地址立即关闭,需用新地址重新登录。
更新界面代码:npx wrangler deploy --keep-vars,无需重新上传 Secrets;手动部署则重新粘贴 worker.js。
升级 Markdown 依赖:修改 src/markdown-browser.js 或升级依赖后执行 npm run build:markdown 重新内嵌进 worker.js。渲染采用 Marked + DOMPurify(标签/属性过滤、链接协议限制),运行不依赖 CDN。
npm install # 安装 wrangler、esbuild、marked、dompurify
npm run dev # 本地启动(读取 .dev.vars 中的 Secrets,KV/限流为本地模拟)
npm test # 16 项自动化测试
npm run build:markdown # 重新内嵌 Markdown 渲染器
npm run deploy # 等价于 npx wrangler deploynpm test 在 Node 中以模拟 KV/限流/代理运行全部路由与安全断言;Node 不支持 Workers 的 MD5 WebCrypto 扩展,测试内以 OpenSSL 等价替代。上线后仍需真实环境验证。
note-worker/
├── worker.js # 完整单文件 Worker(后端 + 内嵌前端),可直接粘贴到控制台
├── src/
│ └── markdown-browser.js # Markdown 渲染源码(marked + DOMPurify 封装)
├── scripts/
│ ├── build-markdown.mjs # 打包 src/markdown-browser.js 并内嵌进 worker.js
│ └── setup-secrets.ps1 # 交互式生成 Secrets(哈希 / 盐 / 会话密钥)
├── test/
│ └── worker.test.mjs # 自动化测试
├── wrangler.jsonc # KV、登录限流绑定等部署配置
└── .gitignore # 已排除 secrets.json / .dev.vars,密钥不入库
| 接口 | 方法 | 说明 |
|---|---|---|
/api/login |
POST | 登录,限流 5 次/分钟/IP,成功签发 8 小时会话 Cookie |
/api/logout |
POST | 退出并清除 Cookie |
/api/session |
GET | 会话有效性检查 |
/api/get-data |
GET | 读取全部笔记与小说(KV 键 user_creative_data) |
/api/save-data |
POST | 全量保存;内容有变化时自动留存历史快照 |
/api/history |
GET | 历史快照列表(最多 10 份,约 10 分钟合并,总量 15 MiB 内) |
/api/history-item?ts= |
GET | 读取指定快照,用于回滚 |
/api/proxy?url= |
GET | 白名单采集代理:逐跳重定向复查、15 秒超时、5 MiB 上限、不转发 Cookie |
- 会话:HMAC-SHA256 签名 Cookie,
HttpOnly; Secure; SameSite=Strict,8 小时,需 HTTPS。签名密钥由SESSION_SECRET、盐、密码、入口路径共同派生,更换任一项即全量失效;无状态会话无法单独吊销已复制的令牌。 - 写请求防护:校验 Origin、自定义请求头、JSON 类型、数据结构及 20 MiB 上限;加载失败时禁止写入默认空数据。
- 页面隔离:首页与错误入口只返回静态展示页,不读 KV、不含私人入口与编辑器脚本。
- 已知取舍:MD5 加盐抗离线破解能力弱,公网长期使用建议迁移 PBKDF2/Argon2;KV 全量保存模型下多标签页并发编辑可能互相覆盖,未实现协同编辑。