Appearance
使用 Nginx 基础认证保护 Nuxt 预发布环境
适用场景
在正式发布前,你需要一个内部测试环境或灰度预览环境,只允许团队成员或特定用户访问,避免被搜索引擎抓取或被外部用户误入。
💡 什么是 Nginx 基础认证
Nginx 基础认证(HTTP Basic Authentication)是一种简单的访问控制方法,通过用户名和密码验证用户身份。搭配 Cloudflare 或防火墙规则,可以实现「白名单 + 密码」双重保护。
前置条件
- 已完成 Nuxt 应用的部署(参考《从零开始部署 Nuxt 应用到 Ubuntu 22.04 服务器》)
- 服务器已安装 Nginx
- 拥有 sudo 权限
1. 安装 apache2-utils 工具
htpasswd 命令包含在 apache2-utils 包中,用于生成加密密码:
bash
sudo apt-get update
sudo apt-get install -y apache2-utils验证安装:
bash
htpasswd -h2. 创建密码文件
创建密码文件并添加第一个用户
bash
# 创建密码文件(-c 表示创建新文件)
sudo htpasswd -c /etc/nginx/.htpasswd your-username
# 系统会提示输入密码两次添加更多用户(不需要 -c 参数)
bash
# 追加用户到已有密码文件
sudo htpasswd /etc/nginx/.htpasswd another-username查看密码文件内容
bash
sudo cat /etc/nginx/.htpasswd
# 输出示例:
# your-username:$apr1$randomhash$xxxxxxxxxxxxx删除用户
bash
# 使用 sed 删除指定用户
sudo sed -i '/username-to-delete/d' /etc/nginx/.htpasswd3. 配置 Nginx 基础认证
方案一:保护整个站点
编辑您的 Nginx 配置文件(如 /etc/nginx/sites-available/myapp):
nginx
server {
listen 80;
server_name pre.your-domain.com;
# 基础认证配置
auth_basic "Restricted Access - Internal Only";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}方案二:保护特定路径
如果只希望保护管理后台或特定路径:
nginx
server {
listen 80;
server_name your-domain.com;
location / {
# 公开访问
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
location /admin {
# 需要认证
auth_basic "Admin Area - Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
location /preview {
# 需要认证
auth_basic "Preview Area - Internal Only";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
}方案三:预发布环境 + IP 白名单双重保护
结合 IP 白名单,实现更精细的访问控制:
nginx
server {
listen 80;
server_name pre.your-domain.com;
location / {
# 允许特定 IP 直接访问(无需密码)
allow 192.168.1.0/24; # 公司内网
allow 10.0.0.0/8; # 企业内网
allow 203.0.113.100; # 特定公网 IP
# 其他 IP 需要密码认证
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
# 拒绝所有未匹配的 IP(这条很重要)
deny all;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}4. 完整配置示例(预发布环境)
以下是针对预发布环境的完整配置示例:
nginx
# /etc/nginx/sites-available/preview
server {
listen 80;
server_name preview.your-domain.com;
# 日志记录
access_log /var/log/nginx/preview-access.log;
error_log /var/log/nginx/preview-error.log;
# 基础认证
auth_basic "Preview Environment - Internal Access Only";
auth_basic_user_file /etc/nginx/.htpasswd;
# 自定义认证提示信息(可选)
auth_basic_user_file /etc/nginx/.htpasswd;
# 超时配置(预发布环境方便调试)
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 静态资源(仍需要认证,但可以缓存)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:3000;
expires 1y;
add_header Cache-Control "public, immutable";
}
# 错误页面(避免泄露信息)
error_page 401 /401.html;
location = /401.html {
auth_basic off;
return 401 '<html><body><h1>Authentication Required</h1><p>This is a private preview environment.</p></body></html>';
}
}5. 启用配置并重启
bash
# 测试配置语法
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx6. 测试访问
浏览器访问
在浏览器中访问 http://preview.your-domain.com,会弹出登录框:
- 用户名:你创建的用户名
- 密码:你设置的密码
命令行测试
bash
# 无认证访问(应返回 401 Unauthorized)
curl -i http://preview.your-domain.com
# 带认证访问
curl -u username:password http://preview.your-domain.com
# 应返回 200 OK7. 配合 Cloudflare 使用(HTTPS + 认证)
如果您使用 Cloudflare,可以同时启用 HTTPS 和基础认证:
nginx
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name preview.your-domain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name preview.your-domain.com;
# Cloudflare Origin CA 证书
ssl_certificate /etc/nginx/ssl/your-domain.pem;
ssl_certificate_key /etc/nginx/ssl/your-domain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
# 基础认证
auth_basic "Preview Environment - Internal Only";
auth_basic_user_file /etc/nginx/.htpasswd;
# Cloudflare 真实 IP
set_real_ip_from 173.245.48.0/20;
# ... 其他 Cloudflare IP 范围 ...
real_ip_header CF-Connecting-IP;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}8. 高级配置技巧
配置认证超时
默认情况下,浏览器会缓存认证信息直到关闭。可以通过以下方式控制:
nginx
# 添加认证过期时间(浏览器支持)
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
# 添加自定义响应头
add_header Cache-Control "no-store, must-revalidate";自定义登录失败提示
nginx
# 自定义 401 错误页面
error_page 401 = @error401;
location @error401 {
auth_basic off;
add_header WWW-Authenticate 'Basic realm="Restricted Access"';
return 401 '<html><body>
<h1>Access Denied</h1>
<p>This preview environment is restricted to internal users only.</p>
<p>Please contact the development team for access.</p>
</body></html>';
}多层级认证
nginx
# 外层基础认证
auth_basic "Outer Protection";
auth_basic_user_file /etc/nginx/.htpasswd-outer;
location / {
# 内层额外认证
auth_basic "Inner Protection";
auth_basic_user_file /etc/nginx/.htpasswd-inner;
proxy_pass http://127.0.0.1:3000;
}9. 密码管理最佳实践
生成强密码
bash
# 使用 openssl 生成随机密码(24位)
openssl rand -base64 24
# 使用 htpasswd 指定 bcrypt 加密(更安全)
htpasswd -B -c /etc/nginx/.htpasswd username定期轮换密码
bash
#!/bin/bash
# update-htpasswd.sh
# 定期更新密码脚本
PASSWORD=$(openssl rand -base64 16)
echo "newuser:$(openssl passwd -6 $PASSWORD)" | sudo tee -a /etc/nginx/.htpasswd
echo "New password for newuser: $PASSWORD"
# 通知团队成员(通过 Slack、邮件等)
# curl -X POST -H 'Content-type: application/json' --data '{"text":"Preview password updated"}' your-webhook-url
sudo nginx -t && sudo systemctl reload nginx安全的密码文件权限
bash
# 确保密码文件权限正确
sudo chmod 640 /etc/nginx/.htpasswd
sudo chown root:www-data /etc/nginx/.htpasswd
# 验证权限
ls -la /etc/nginx/.htpasswd
# 应输出:-rw-r----- 1 root www-data ...10. 与自动部署脚本集成
在之前文章的 deploy.sh 基础上,增加预发布环境的部署:
bash
#!/bin/bash
# deploy-preview.sh - 部署到预发布环境
SERVER="root@your-server-ip"
APP_PATH="/var/www/preview-app"
PM2_NAME="preview-app"
# 构建
echo "📦 Building preview..."
pnpm build
# 打包
echo "📁 Packaging..."
tar -czf deploy.tar.gz -C .output .
# 上传
echo "📤 Uploading..."
scp deploy.tar.gz $SERVER:$APP_PATH/
# 部署并确保基础认证配置生效
ssh $SERVER "cd $APP_PATH && \
tar -xzf deploy.tar.gz && \
pm2 reload $PM2_NAME && \
rm deploy.tar.gz && \
echo '✅ Preview deployment complete!'"
rm deploy.tar.gz11. 常见问题处理
Q1: 浏览器不弹出登录框
原因:可能是认证配置语法错误或密码文件路径不对。
bash
# 检查 Nginx 配置
sudo nginx -t
# 检查密码文件
sudo cat /etc/nginx/.htpasswd
# 检查 Nginx 错误日志
sudo tail -f /var/log/nginx/error.logQ2: 登录后仍然 401
原因:密码错误或加密方式不兼容。
bash
# 重新生成密码(使用 MD5 加密,兼容性最好)
sudo htpasswd -c /etc/nginx/.htpasswd username
# 重启 Nginx
sudo systemctl restart nginxQ3: 静态资源也被认证拦截
解决方案:将静态资源路径配置为不需要认证:
nginx
location /_nuxt/ {
auth_basic off;
proxy_pass http://127.0.0.1:3000;
}Q4: 如何临时禁用认证
nginx
# 注释掉认证相关配置即可
# auth_basic "Restricted Access";
# auth_basic_user_file /etc/nginx/.htpasswd;
# 重载配置
sudo nginx -s reload12. 安全建议
| 建议 | 说明 |
|---|---|
| 使用 HTTPS | 基础认证的密码是 Base64 编码,必须配合 HTTPS 使用 |
| 限制 IP | 结合 IP 白名单,减少密码暴露风险 |
| 定期轮换 | 定期更换密码,特别是人员变动时 |
| 使用强密码 | 密码至少 16 位,包含大小写字母、数字、特殊字符 |
| 日志监控 | 监控 access.log,发现异常访问及时处理 |
| 不用于高敏感场景 | 基础认证适合预发布环境,生产环境建议使用 OAuth/JWT |
结语
通过 Nginx 基础认证,你可以快速搭建一个受保护的预发布环境,让团队成员在安全的环境中进行测试和验收。
这种方案的优势在于:
- 零代码改动:无需修改 Nuxt 应用代码
- 配置简单:几行 Nginx 配置即可完成
- 即时生效:修改配置后
nginx -s reload即可 - 资源占用低:Nginx 原生支持,性能影响极小
配合上一篇文章的完整部署流程,你可以轻松实现:
- 生产环境:公开访问 + Cloudflare CDN
- 预发布环境:密码保护 + IP 白名单
延伸阅读
- 从零开始部署 Nuxt 应用到 Ubuntu 22.04 服务器 - 包含完整的部署流程及 Cloudflare Origin CA 证书配置(方案二)