mcpField
N
netlify-access-control

netlify-access-control

github.com/netlify安全472.3k 次安装6 天前更新
代码仓库

关于 netlify-access-control

netlify-access-control 是帮助 Netlify 用户选择站点保护方式的技能,面向需要限制站点、预览或页面访问的团队。它区分应用用户身份、站点访问保护和团队 SSO,并提供决策指引与控制台操作路径。

主要功能

  1. 01区分三类身份验证
  2. 02按访问需求选择保护层
  3. 03说明私有项目与共享密码差异
  4. 04提供控制台设置路径
  5. 05提示计划限制与常见问题

适用场景

  1. 01限制团队成员访问整个站点
  2. 02仅保护预览部署
  3. 03为特定页面设置多密码保护
  4. 04排查 SSO 过期导致的 401

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/netlify/context-and-tools --skill netlify-access-control

安装后在 Claude Code 中输入/netlify-access-control确认已加载。

附带文件references/two-layer-pattern.md

详细介绍

Netlify 访问控制——选择保护层

此技能会引导你选择正确的保护层,但不会讲解每种保护方式。**这些设置没有公开 API、CLI 命令或 MCP 工具。**切勿通过 curl api.netlify.com 或读取本地身份验证令牌来检查或更改这些设置——请向用户提供控制面板路径和检查清单。失败时,报告你尝试了什么,然后停止。

首先:明确“auth”的含义——三个互不相关的层

用户经常混淆这几种情况。提供建议前,先确认他们指的是哪一种。

  1. Netlify Identity——“这个用户在我的应用内部是谁。”会签发 nf_jwt。→ 转到 netlify-identity 技能;此处不作介绍。
  2. 密码保护 / 项目可见性——“此请求能否加载网站。”此处介绍。
  3. 团队/组织 SAML SSO——“你能否登录 Netlify 控制面板。”控制面板访问受此限制;团队登录网站保护也基于此。

会话彼此独立。同一个提供商(例如 Google)可能出现在两个互不相关的场景中——供应用用户使用的 Identity OAuth,以及供团队成员使用的 SAML IdP。

双重登录陷阱:密码保护/团队登录的边界会话与 Identity 应用会话之间没有桥接机制——没有共享 Cookie、没有请求头转发,也没有 JWT 交换。不要尝试将它们连接起来。有关组合分层模式及其权衡,请参阅 references/two-layer-pattern.md。Netlify 登录本身可以触达应用代码:对于私有项目或启用了团队登录保护的项目,函数和边缘函数会通过 context.user 接收已登录的 Netlify 用户——如果所有应用用户都能通过该登录验证,它就是应用的身份,无需第二次登录。

**想要一个只需单次登录(无双重登录)的内部应用?**先询问谁会使用它:

  • 他们可以通过项目的 Netlify 登录验证 → 使用私有项目(按用量计费的计划;若使用者包括团队所有者以外的人员,则需 Pro)或团队登录保护(Enterprise),并在函数中使用 context.user 实现针对个人的行为。
  • 他们无法通过验证(例如,没有 Netlify 席位的员工)→ 在双层方案之前,使用 Auth0 extension 联合企业 IdP。

决策指南(此技能的用途)

  • 将整个网站限制为团队成员访问,通过电子邮件邀请 → 私有项目(按用量计费)或团队登录保护(密码保护)。
  • 与持有同一共享密码的任何人分享 → 基本密码保护(Pro)或 Password 可见性(仅适用于按用量计费计划的 Pro)。按用量计费计划的 Free/Personal 不提供此功能——请改为将项目设为私有。
  • 保持生产环境公开,仅保护预览 → 将范围设为仅限预览 / 仅限非生产部署。
  • 要求通过 SSO 查看网站 → 使用组织/团队 SSO,并启用 Only SSO allowed (strict),然后使用密码保护并启用团队登录保护。
  • 确认是哪位团队成员发出了请求 → 使用私有项目或团队登录保护,然后在函数/边缘函数中读取 context.user(基本密码保护不提供相关说明)。
  • 使用多个密码保护特定页面/版块 → 使用自定义 HTTP headers 的基本身份验证(原名 Selective password protection):https://docs.netlify.com/manage/security/secure-access-to-sites/basic-authentication-with-custom-http-headers/
  • 验证你自己的最终用户 → Netlify Identity / OAuth provider tokens / Role-based access control with JWT → 转到 netlify-identity。
  • 阻止恶意/自动化流量或 AI 爬虫 → Advanced Web Security(WAF / Firewall Traffic Rules / 速率限制)或 User Agent Blocker 扩展:https://docs.netlify.com/build/build-with-ai/block-ai-crawlers/

关键区别:Private 与 Password

  • Private 已要求提供 Netlify 凭据——无需共享密码。通过电子邮件邀请;建议用于仅限团队访问。
  • Password = 所有人都能使用的通用共享密码(包括管理团队成员,他们也必须输入密码)。不支持 SSO。无法识别单个访客。
  • 团队登录保护 = 与 Private 使用相同的机制:访客必须以 Netlify 团队成员身份登录;你邀请的 Reviewers 也能访问(数量不限,且在旧版套餐中不计入成员数;基于 Credit 的套餐需 Pro 或更高版本)。Git Contributors 无法登录——请将他们邀请为 Reviewers,而不是将其升级为 Developer。

识别访客:context.user

启用团队登录保护或使用私人项目时,函数和边缘函数会通过 context.user 获取已登录的 Netlify 用户。不要猜测其字段——请参阅 https://docs.netlify.com/build/functions/api/#user 和 https://docs.netlify.com/build/edge-functions/api/#user。

SSO 会话现象:约 1 小时后出现 401 错误

如果用户反映自己“会话中途被登出”或 SSO 保护的网站出现 401 错误:SSO 身份验证令牌会在 1 小时后过期,之后请求会返回 401。启用了 SSO 保护的网站会返回标头 Netlify-Site-Protection-Expires-In——表示请求令牌过期前的秒数。请主动刷新:

// Client-side. Checks the Netlify SSO protection header and reloads before expiry.
const res = await fetch(window.location.href, { method: "HEAD" });
const secondsLeft = Number(res.headers.get("Netlify-Site-Protection-Expires-In"));
// Tokens last 1 hour (3600s). Reload a bit early to avoid a 401.
if (!Number.isNaN(secondsLeft) && secondsLeft < 60) {
  window.location.reload();
}

UI 路径(唯一途径——无 API)

基于 Credit 的套餐(Free、Personal、Pro)——项目级“Password Protection”已替换为项目可见性:

  • 每个项目:Project configuration > General > Visitor access > Project visibility — https://app.netlify.com/projects/{site_name}/configuration/general/#project-visibility。Edit visibility →(如果存在团队默认设置,则选择 Customize)→ Public / Password(仅 Pro)/ Private → 设置 Preview access(Production and previews / Previews only)→ Save。
  • Free/Personal 没有 Password 选项——使用 Private 限制查看者(仅 Team Owner 可见;邀请他人需要 Pro)。
  • 团队默认设置:Team settings > General > Visitor access > Default project visibility — https://app.netlify.com/teams/{team_name}/settings/general#default-project-visibility。选项:新项目设为 Private / 所有项目设为 Private / 新项目设为 Public。
  • 此处没有按团队设置的默认 password;请为每个项目设置密码。

Enterprise / Open Source / 旧版(非基于 Credit)——使用 Password Protection UI:

  • 每个站点:Project configuration > General > Visitor access > Password Protection — https://app.netlify.com/projects/{site_name}/configuration/general#visitor-access。Configure → Basic 或 Team login → 范围(All deploys / Non-production deploys only)→ Save。
  • 团队默认设置:Team settings > Access & security > Visitor access > Default Password Protection settings — https://app.netlify.com/teams/{team_name}/settings/access#default-site-protection-settings。适用于所有未配置自身设置的站点。

**旧版 → 基于 Credit 的套餐映射:**无保护→Public · Basic protection→Password(仅 Pro)· Team protection→Private · All deploys→Production and previews · Non-production deploys only→Previews only。

限制与注意事项

  • 站点级密码保护会覆盖团队默认设置。
  • **谁可以更改这些设置:**项目可见性——组织所有者(适用于某些 Enterprise 计划)、团队所有者,以及有权访问该项目的开发者;Internal Builders 无法发布到生产环境,因此无法将项目设为公开。密码保护——开发者可针对每个站点进行更改,团队所有者可设置团队默认值。
  • 高级 Web 安全会在密码/登录提示之前运行——被拦截的 IP 会先看到错误页面,而不是提示。内部顺序:防火墙流量规则 → WAF → 速率限制。
  • 第三方 Webhook(Slack、Stripe 等)无法访问私有项目——接收 Webhook 要求项目为公开。
  • 设为公开要求至少成功进行一次生产环境部署。
  • 仅保护非生产环境部署的密码保护功能仅限 Enterprise。
  • **计划限制:**对整个站点启用基本密码保护 → 所有 Pro 计划;所有密码保护选项 → Enterprise。**基于额度的 Free/Personal 计划不提供密码保护。**项目可见性(公开/私有、默认设为私有)→ 仅限基于额度的 Free/Personal/Pro 计划;受密码保护的可见性 → 仅限 Pro。Free/Personal 计划中的私有项目仅团队所有者可见(单席位);Pro 允许无限成员。
  • 团队默认设置因创建日期而异:于 2026 年 7 月 28 日或之后创建的团队,新项目默认设为私有;此前创建的团队默认设为公开。
  • 已重命名:“站点范围密码保护”(密码保护某个选项的旧名称);“选择性密码保护” → 使用自定义 HTTP 标头进行基本身份验证。

参考:https://docs.netlify.com/manage/security/secure-access-to-sites/overview/ · https://docs.netlify.com/manage/security/secure-access-to-sites/password-protection/ · https://docs.netlify.com/manage/security/secure-access-to-sites/project-visibility/

Netlify 规则(访问控制)

这些是组织约定,而非文档事实——由 ctx-gen 合并到渲染后的技能中,且不会自动生成。由技能维护者负责维护。

  1. 这是一个用于路由和消歧的技能:范围要明确——它负责选择正确的保护层,而不是讲解每种保护层。
  2. Password-Protection 与 Identity 组合模式位于此技能的 references/two-layer-pattern.md。
  3. Netlify 上的“Auth”包含三个互不相关、用户却经常混淆的层:Netlify Identity(“此用户在我的应用中是谁”——会签发 nf_jwt)、Password Protection/项目可见性(“此请求能否加载网站”),以及 Team/Org SAML SSO(“你能否登录 Netlify 控制面板”)。会话彼此独立;同一个提供商(Google)可能出现在两个互不相关的位置——面向应用用户的 Identity OAuth,以及面向团队成员的 SAML IdP。提出建议前,先消除歧义。
  4. 团队登录或私有项目会话与 Identity 应用会话之间确实会出现双重登录:没有共享 Cookie、没有标头转发,也没有 JWT 交换。不要浪费迭代去连接这两者;权衡取舍见 references/two-layer-pattern.md。Netlify 登录本身确实能触达应用代码:在私有项目上,或启用团队登录保护时,函数和边缘函数会通过 context.user 收到已登录的 Netlify 用户。如果使用该应用的每个人都能通过此登录,它就能作为应用的身份验证,无需第二次登录。
  5. 这些设置没有公共 API、CLI 命令或 MCP 工具。绝不要 curl api.netlify.com,也不要读取本地身份验证令牌来检查或更改这些设置——应告知用户控制面板路径和检查清单;如果失败,说明尝试过什么,然后停止。
  6. 面向应用用户的 Identity 设置、身份验证代码和 OAuth 提供商属于 netlify-identity 技能——应转到该技能;此技能只负责选择保护层。
  7. 对于只有一种登录方式的内部应用,先询问使用者是谁。如果他们能通过项目的 Netlify 登录,则建议使用私有项目(按 Credit 计费的套餐;Team Owner 以外的任何人都需要 Pro)或团队登录保护(Enterprise),并在函数中使用 context.user 实现针对个人的行为。如果他们无法通过登录,例如没有 Netlify 席位的员工,则应优先建议通过 Auth0 扩展与企业 IdP 联合身份验证,而不是采用双层方案。
  8. 描述中的触发条件必须包含用户实际报告的 SSO 会话症状——“会话中途被登出”、受 SSO 保护的网站返回 401、令牌过期/刷新——不能只包含设置相关措辞。如果技能不会因症状而触发,就无法触达 Netlify-Site-Protection-Expires-In 相关指导。
  9. 团队登录保护不包含 Git Contributors;对此的解决方案是 Reviewers,绝不是 Developer 席位。Reviewers 可以打开受团队登录保护的部署:在旧套餐中数量不限,且不计入成员数;在按 Credit 计费的套餐中,需要 Pro 或更高套餐。每个关于 Git Contributor 访问权限的答复都必须说明 Reviewer 方案——建议升级到 Developer,等于让每个人都购买付费席位来解决产品已有的免费方案可以解决的问题。不说明解决办法,只陈述不包含 Git Contributors,就是本规则要防止的失误;这种情况已经发生。绝不要把允许的角色描述成封闭列表(“只有 X、Y 和 Z 可以访问”)——即使后面补上 Reviewer 方案,封闭列表仍会让人以为 Reviewers 不能访问,而且 Agent 会照搬这种说法。通常问题只涉及 Git Contributors,因此无需列出角色。
  10. 不仅要说明如何更改这些设置,还要说明谁可以更改。项目可见性:Organization Owners(部分 Enterprise 套餐)、Team Owners,以及有权访问该项目的 Developers;Internal Builders 无法将项目设为公开,因为他们不能发布到生产环境。Password Protection:每个站点的 Developer,或团队默认设置的 Team Owner。把检查清单交给没有相应权限的人,只会让事情陷入僵局。

评论

支持 Markdown