最近我在发布自己的第一个 npm 包时,踩了一个比较典型的坑:
明明已经登录了 npm,执行 npm publish 时却一直报 403 Forbidden。
最终我通过 Access Token 成功把包发上去了。这里把整个过程记录下来,希望能帮到遇到同样问题的人。
一、我的场景
我要发布的包是一个 scoped package,大概像这样:
json
{
"name": "@halfofpeotry/kbc",
"version": "0.1.0"
}
我是在 Linux 环境下操作的,项目目录类似这样:
bash
/root/github/knowledge-base-for-code
一开始我以为只要:
bash
npm login
npm publish --access public
就可以直接发布,但结果报错了。
二、我遇到的报错
发布时终端输出类似下面这样:
bash
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
npm error code E403
npm error 403 403 Forbidden - PUT https://registry.npmjs.org/@halfofpeotry%2fkbc - Two-factor authentication or granular access token with bypass 2fa enabled is required to publish packages.
日志里还有这些关键信息:
bash
verbose statusCode 403
verbose pkgid @halfofpeotry/kbc@0.1.0
verbose cwd /root/github/knowledge-base-for-code
三、问题原因
一开始看到 403,我还以为是:
- 包名被占用了
- 权限不够
- registry 配错了
- scoped package 没有加
--access public
但实际上,这次真正的原因是:
npm 对发布操作有更严格的安全要求。
发布包时,需要满足以下条件之一:
- 开启 2FA(双重验证)
- 使用支持发布且允许绕过 2FA 的 Access Token
而我当时的账号并没有开启 2FA,所以普通登录方式没法完成发布。
四、为什么我最后选择 Access Token
理论上我有两种解决办法:
方案 1:开启 2FA
开启 npm 账号的双重验证,然后在发布时输入 OTP 动态验证码。
方案 2:使用 Access Token
创建一个具有发布权限的 token,在命令行中使用 token 认证来发布。
因为我这次是在服务器/root 环境下操作,
而且后面也可能会接入自动化发布,所以我最终选择了 Access Token 的方式。
五、我是怎么操作的
1. 先确认 registry 是官方源
发布 npm 包必须使用官方 registry,我先检查了一下:
bash
npm config get registry
正确结果应该是:
bash
https://registry.npmjs.org/
如果不是,就切换成官方源:
bash
npm config set registry https://registry.npmjs.org/
2. 登录 npm 官网创建 Access Token
我登录了 npm 官网:
然后进入账号设置里的 Access Tokens 页面,创建了一个新的 token。
这里我选择的是适合发布的 token,并确保它具备:
- 对目标包的发布权限
- 满足 npm 当前安全策略的权限要求
如果你是自动化发布场景,建议优先使用 npm 官方推荐的 token 类型。
3. 在命令行中配置 token
拿到 token 之后,我在当前环境执行:
bash
npm config set //registry.npmjs.org/:_authToken=你的token
这样 npm 后续在访问官方 registry 时,就会自动带上这个 token。
我也可以通过查看配置文件确认是否写入成功:
bash
cat ~/.npmrc
通常会看到类似内容:
ini
//registry.npmjs.org/:_authToken=xxxxxxxxxxxx
4. 确认当前包信息没问题
发布前,我又确认了一下 package.json 中的几个关键字段:
json
{
"name": "@halfofpeotry/kbc",
"version": "0.1.0",
"main": "index.js",
"license": "MIT"
}
重点检查了这几个点:
name是否正确version是否是一个没发布过的新版本- scoped package 是否属于我自己的 scope
5. 开始发布
因为我的包是 scoped package,所以发布时加上:
bash
npm publish --access public
这一次终于成功了。
六、为什么 scoped package 要加 --access public
这是我一开始比较容易忽略的点。
像这种包名:
bash
@halfofpeotry/kbc
属于 scoped package 。
scoped package 首次发布时,如果我希望它是公开包,就要显式加上:
bash
npm publish --access public
否则可能会因为默认访问级别的问题导致发布失败。
七、我这次踩坑后的经验总结
这次发包虽然不复杂,但我总结了几个很实用的经验。
1. 403 不一定是包名冲突
很多时候看到 403,第一反应是"是不是没权限"。
实际上 npm 的 403 很多是认证策略问题,尤其是 2FA / token 权限 相关。
2. 服务器环境更适合用 token
如果是在本地偶尔手动发包,2FA + OTP 其实也可以。
但如果是在:
- 云服务器
- Docker 容器
- CI/CD
- GitHub Actions
这种环境里,Access Token 明显更方便。
3. 一定要用官方 registry
发布 npm 包时,必须是:
bash
https://registry.npmjs.org/
如果你平时用的是淘宝镜像之类的镜像源,安装依赖没问题,
但发布包时必须切回官方源。
4. 每次重新发布都要升级版本号
如果 0.1.0 已经发布成功了,再次发布时不能继续发同一个版本。
这时要先修改版本号,例如:
bash
npm version patch
然后再执行:
bash
npm publish --access public
八、我最终成功发布的核心命令
如果让我把这次成功经验浓缩成最关键的几步,就是下面这些:
检查官方源
bash
npm config get registry
npm config set registry https://registry.npmjs.org/
配置 token
bash
npm config set //registry.npmjs.org/:_authToken=你的token
发布 scoped public 包
bash
npm publish --access public
九、我建议发布前顺手做的检查
为了避免发错内容,我现在会在发布前多做几步。
查看当前登录配置
bash
cat ~/.npmrc
检查当前用户
bash
npm whoami
查看即将发布的包内容
bash
npm pack --dry-run
这个命令特别有用,它能让我提前看到哪些文件会被打包发布,
避免把不该传上去的文件也发出去。
十、写在最后
这是我第一次通过 Access Token 成功发布 npm 包。
整个过程让我真正理解了两件事:
- npm 发布不仅仅是
npm publish这么简单 - 认证方式和安全策略,往往才是发布失败的关键原因
如果你也遇到了类似错误:
bash
403 Forbidden - Two-factor authentication or granular access token with bypass 2fa enabled is required to publish packages
而你又不想折腾 2FA,那么直接改用 Access Token,通常就是最直接的解决方案。
附:我的最终发布命令
bash
npm config set registry https://registry.npmjs.org/
npm config set //registry.npmjs.org/:_authToken=你的token
npm publish --access public
如果这篇记录对你有帮助,那我这次踩坑就算值了。