shadcn/ui 私有 Registry 如何配置 Token 认证来控制内部组件的访问权限?
2026/9/9 22:23:45 网站建设 项目流程

shadcn/ui 私有 Registry 如何配置 Token 认证来控制内部组件的访问权限?

【免费下载链接】uiA set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks. Open Source. Open Code.项目地址: https://gitcode.com/GitHub_Trending/ui/ui

团队内部有一套组件库不想放到公开仓库,希望只有持有 token 的人才能通过 shadcn CLI 安装。shadcn/ui 的 Registry 机制支持在components.jsonregistries字段里为某个命名空间配置认证头,Registry 服务端校验 token 后再返回组件 JSON,未授权请求会得到 401/403 而不是组件内容。本文基于项目文档 authentication.mdx 和 namespace.mdx 说明完整的配置路径:服务端校验 → 消费端配置 → 本地验证。

前置条件:你已有一个能对外提供 Registry JSON 的项目(参照 getting-started.mdx,根目录有registry.json,可通过npx shadcn@latest build生成静态 JSON,或用shadcn/registryloadRegistryItem走动态路由)。

Registry 服务端:在路由里校验 token

以 Next.js API 路由为例,文档给出的实现位于app/api/registry/[name]/route.ts。核心逻辑分三层:解析 token、校验 token 有效性、校验该 token 对目标组件的访问权。

import { NextRequest, NextResponse } from "next/server" export async function GET( request: NextRequest, { params }: { params: { name: string } } ) { // Get token from Authorization header. const authHeader = request.headers.get("authorization") const token = authHeader?.replace("Bearer ", "") // Or from query parameters. const queryToken = request.nextUrl.searchParams.get("token") // Check if token is valid. if (!isValidToken(token || queryToken)) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } // Check if token can access this component. if (!hasAccessToComponent(token, params.name)) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }) } // Return the component. const component = await getComponent(params.name) return NextResponse.json(component) } function isValidToken(token: string | null) { // Add your token validation logic here. // Check against database, JWT validation, etc. return token === process.env.VALID_TOKEN } function hasAccessToComponent(token: string, componentName: string) { // Add role-based access control here. // Check if token can access specific component. return true // Your logic here. }

注意两个判断的区别:isValidToken决定 token 本身是否有效,无效返回 401;hasAccessToComponent决定该 token 能否取这个具体组件,无权返回 403。文档中的isValidToken示例只做了与process.env.VALID_TOKEN的字符串比较,注释里明确提示这里应替换为你的校验逻辑(数据库、JWT 等);hasAccessToComponent示例直接返回true,同样需要按自己的权限模型实现。Express 服务端有对应的更短示例,同样是先 401 后取组件。

消费端:在 components.json 中声明认证头

使用方在项目根目录的components.json里用对象形式配置命名空间,headers中的${REGISTRY_TOKEN}会被 CLI 在运行时从环境变量展开(文档明确说明:${VAR_NAME}形式的环境变量会在 URL、headers 和 params 中自动替换):

{ "registries": { "@private": { "url": "https://registry.company.com/{name}.json", "headers": { "Authorization": "Bearer ${REGISTRY_TOKEN}" } } } }

token 本身写在.env.local,不要提交到版本库:

REGISTRY_TOKEN=your_secret_token_here

your_secret_token_here和 URL 中的registry.company.com都是文档示例值,替换为你实际签发的 token 和 Registry 域名。{name}是 CLI 要求的 URL 占位符,安装@private/button时会被替换为https://registry.company.com/button.json

如果环境变量没设置,CLI 会直接报错而不是发请求,文档给出的报错示例如下:

Registry "@private" requires the following environment variables: • REGISTRY_TOKEN Set the required environment variables to your .env or .env.local file.

验证配置是否生效

文档给出两条验证命令,都在本地可执行。

用 curl 直接验证服务端鉴权(token 换成真实值,URL 换成你的 Registry 地址):

# Test with curl. curl -H "Authorization: Bearer your_token" \ https://registry.company.com/button.json

用 CLI 走完整安装链路:

# Test with the CLI. REGISTRY_TOKEN=your_token npx shadcn@latest add @private/button

判断依据:带有效 token 的请求返回组件 JSON(安装成功写入文件);无效或缺失 token 返回 401,token 无权访问该组件返回 403。文档还说明 CLI 会优雅处理这些认证错误,且支持自定义错误消息——服务端可以在响应体里加message字段,CLI 会把这段文字展示给用户,例如:

return NextResponse.json( { error: "Unauthorized", message: "Token expired. Request a new token at company.com/tokens", }, { status: 401 } )

这样可以在提示里区分「token 过期」和「权限不足」,对应文档中!tokenisExpiredToken(token)!hasTeamAccess(token, component)三种分支。

可选分支:其他认证形式

如果服务端不适合用 Bearer token,文档给出了两种替代,配置方式相同(都在registries的对象形式里):

  • API Key 头"headers": { "X-API-Key": "${API_KEY}" },可再加X-Workspace-Id等工作区标识头。
  • Query 参数"params": { "token": "${ACCESS_TOKEN}" },最终请求形如https://registry.company.com/button.json?token=your_token

安装前想检查组件内容时,view命令同样走这套认证配置:

npx shadcn@latest view @private/button

安全边界与文档给出的约束

以下几点是文档明确的限制和建议,配置时注意:

  • Registry URL 必须用 HTTPS。文档把http://标注为应避免的写法,token 会在传输中明文暴露。
  • token 只放环境变量。CLI 对认证用环境变量的处理是:从不打印其值、运行时才展开、每个 Registry 各自维护独立的认证上下文。
  • 静态 JSON 文件本身不鉴权。如果你按 getting-started.mdx 的 Option A 用shadcn build输出静态文件到public/r,文件对任何能访问该 URL 的客户端都是可读的;token 认证必须走动态路由(Option B)或在你自己的服务端实现校验,这也是本文服务端章节存在的原因。
  • GitHub 地址暂不支持私有仓库鉴权以外的方式。faq.mdx 说明 GitHub registry 地址当前只支持公开仓库,私有 Registry 应使用带认证的命名空间 URL;changelog 2026-08 补充了通过 GitHub CLI 登录或GH_TOKEN读取私有仓库的路径,那是针对owner/repo/item形式地址的独立机制,与本文的命名空间 token 配置不冲突。

多命名空间混用

如果同时存在公开和私有 Registry,可以在同一个components.json里为不同命名空间配不同认证,公开的不配 headers:

{ "registries": { "@public": "https://public.company.com/{name}.json", "@internal": { "url": "https://internal.company.com/{name}.json", "headers": { "Authorization": "Bearer ${INTERNAL_TOKEN}" } } } }

文档指出这用于按访问级别组织组件:公开库无需认证,内部库和付费库各自带独立的认证头。

进一步的团队级访问控制(按 team 返回不同组件)、临时过期 token、限流等模式见 authentication.mdx 的 Advanced Patterns 与 Security Best Practices 章节,多 Registry 的组合规则见 namespace.mdx。

【免费下载链接】uiA set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks. Open Source. Open Code.项目地址: https://gitcode.com/GitHub_Trending/ui/ui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询