文章密码与服务端访问
文章密码由 Next.js 服务端验证。公开页面数据只包含 password: "protected" 标记、标题和摘要;正文和目录在验证成功后由 POST /api/post/unlock 返回,并设置 no-store。
- 支持 SHA-256 及历史
md5(slug + password)摘要。 - 内置主题的密码框等待异步验证结果,包括 OPC 和 Landing。自定义主题应使用
await validPassword(password),返回值仍为布尔值。 - 验证成功会返回正文、上一篇、下一篇及推荐文章。服务暂不可用和密码错误有不同反馈。
- 旧密码 URL 和 localStorage 只尝试迁移一次,随后清除;新密码不写入 localStorage。刷新页面后需重新解锁。
- 密码文章解锁需要服务端。
EXPORT=true仍会成功生成密码文章的锁页,保留标题、摘要和保护标记,页面明确提示当前静态站点不能解锁,不渲染密码表单。导出时不预取这些文章的正文,即使调用者提供正确密码也不会导出正文。公开文章继续正常导出。 - UUID 入口必须属于本站目录或已发布目录文章的子页面,并继承目录祖先的密码要求。公开发布
Published与隐藏发布Invisible都允许其子页面通过 UUID 访问;隐藏发布仍不出现在文章列表中,草稿Draft不放行。notion-client@7.12.1的getPage只补齐缺失的内容块,不保证返回完整祖先链;服务端因此沿parent_id补拉缺失的 block/collection 记录,最多检查 64 层。链缺失、循环、跨工作区、祖先未发布或无法找到目录祖先时返回 404。 - 仅同工作区但未关联已发布目录的独立 UUID 页面不会放行。Notion 客户端可能携带服务端 token,能读到页面不等于页面公开;要通过本站访问此类页面,请将其加入本站目录并发布。补拉的祖先记录只用于校验,不加入对浏览器返回的正文数据。
- 公共文章预览、搜索和 RSS 不应包含密码页面的嵌套正文。Algolia 不上传密码文章;已生成的旧索引和静态文件应在更新后重新生成。
接口按 IP 提供每分钟 20 次的单实例内存限流,最多保留 10000 个地址窗口,满额时淘汰最旧窗口,不会因此拒绝所有新访客。该限流只是本地兜底:Serverless 冷启动、多实例和地址轮换会削弱效果;需要统一约束时必须在可信网关配置共享限流。
自托管反向代理只有在入口不可绕过、且代理会覆盖客户端传入的转发头时才设置 TRUST_PROXY=true。代理必须覆盖 X-Forwarded-For、X-Forwarded-Host(浏览器访问的主机名与可选端口)和 X-Forwarded-Proto(http 或 https),不要追加逗号分隔的值。VERCEL=1 平台环境也会使用可信转发头。其他部署忽略转发头,使用实际 Host 和 TLS 状态校验完整 Origin;错误协议、端口、来源及歧义头会被拒绝。
公开文章只在构建或静态导出时允许降级:Notion 正文获取或适配失败时使用安全摘要;目录、AI 摘要等后处理失败时,保留处理前已完成隐私过滤的正文快照,丢弃未完成的派生内容。运行时 ISR(包括按需刷新)遇到这些异常会抛错,保留上一次成功页面,避免用摘要页覆盖完整正文;首次动态生成没有旧页面可用时会返回错误,稍后可重试。构建阶段由 Next.js 的 revalidateReason: 'build' 标识判断,不以可能残留在部署环境中的 BUILD_MODE 判断。
已通过密码验证的文章遇到同类失败始终抛出错误,解锁接口返回 503。全站目录加载失败的兜底数据会保留内部失败标记(不传给浏览器),运行时文章解析不会把兜底目录误认成文章已删除。UUID 页面若确认祖先链不符合访问要求则返回 404;运行时重试耗尽返回空值、工作区暂不可确认或获取过程抛错时会保留错误,不以临时 404 覆盖已有页面,也不会降级放行。错误提示使用当前语言字典。
此功能限制本站的正文访问;Notion 原页面自身的公开分享权限仍由 Notion 管理。
