尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

htpasswd 实战:给你的 Nginx 加把锁,三分钟搞定 Basic Auth

htpasswd 实战:给你的 Nginx 加把锁,三分钟搞定 Basic Auth 摘要htpasswd Nginxauth_basic三分钟给 Grafana、Kibana 等内部工具加 Basic Auth讲-c/-b/-B/-D参数、加密算法选型、没装环境时用 Docker 生成密码文件以及保护整站/指定路径、健康检查免密、代理自带认证后端清Authorization头避免 401。两个前提Basic Auth 是 Base64 编码不是加密、必须配 HTTPSbcrypt 取决于系统crypt()不是 Nginx 版本。Grafana 监控面板、RocketMQ Dashboard、Kibana、Redis Insight……这些内部管理工具你是不是也裸奔在公网上“没事知道地址的人不多。”——直到某天你发现 ES 被人清空了数据才意识到安全问题有多严重。本文教你用htpasswd Nginxauth_basic三分钟给任何 Web 服务加上密码保护简单粗暴但有效。一、htpasswd 是什么htpasswd是 Apache 提供的一个密码文件管理工具用来生成和管理 HTTP Basic Auth 的用户名/密码文件。虽然它是 Apache 的工具但Nginx 也完美支持这种密码文件格式。说白了它帮你生成一个用户名:加密密码格式的文件Nginx 读这个文件来验证访问者身份。整个 Basic Auth 的握手过程是这样的——注意第 ③ 步.htpasswdNginx浏览器.htpasswdNginx浏览器浏览器弹出账号密码框⚠️ 这一步只是 Base64 编码不是加密base64 -d 一秒还原出 admin:pass所以裸 HTTP 下等于明文传密码 —— 必须配 HTTPS① GET /grafana② 401 UnauthorizedWWW-Authenticate: Basic realmRestricted③ GET /grafanaAuthorization: Basic YWRtaW46cGFzcw④ 按用户名取密码哈希$2y$05$...bcrypt⑤ 用同样算法校验⑥ 200 OK 401 重新弹框这张图说明了本文最重要的一件事Authorization: Basic后面那串东西只是 Base64 编码不是加密——echo YWRtaW46cGFzcw | base64 -d一秒还原出admin:pass。所以裸 HTTP 下用 Basic Auth 等于明文传密码中间任何一跳抓包都能拿到。换句话说htpasswd 用什么加密算法MD5 还是 bcrypt保护的是「服务器上那份密码文件」不是「传输过程」。前者靠-B后者只能靠 HTTPS两件事不能互相替代。二、安装# Debian / Ubuntuapt-getinstall-yapache2-utils# CentOS / RHELyuminstall-yhttpd-tools# macOSbrewinstallhttpd没有安装条件用 Docker 临时生成也行见第四节。三、常用命令1. 创建密码文件 添加第一个用户# -c 创建新文件如果文件已存在会被覆盖htpasswd-c/etc/nginx/conf.d/.htpasswd admin# 交互式输入密码输入两次第一次用-c之后不要再用-c否则会覆盖整个文件之前的用户全没了。这是最常见的翻车姿势。2. 追加用户不覆盖# 不加 -c追加用户到已有文件htpasswd /etc/nginx/conf.d/.htpasswd zhangsan3. 命令行直接传密码非交互式# -b 从命令行传密码适合脚本自动化htpasswd-b/etc/nginx/conf.d/.htpasswd lisi MyPssw0rd注意密码会出现在 shell 历史记录里用完记得history -d清掉或者用HISTCONTROLignorespace 命令前加空格。4. 只输出不写文件# -n 输出到终端不写文件适合调试或管道操作htpasswd-nbadmin MyPssw0rd# 输出admin:$apr1$xyz$abcdefg...5. 删除用户# -D 删除指定用户htpasswd-D/etc/nginx/conf.d/.htpasswd zhangsan6. 验证密码是否正确# -v 验证密码htpasswd-v/etc/nginx/conf.d/.htpasswd admin四、参数速查表参数作用示例-c创建新文件会覆盖htpasswd -c file user-b命令行传密码非交互htpasswd -b file user pass-n输出到终端不写文件htpasswd -nb user pass-D删除用户htpasswd -D file user-v验证密码htpasswd -v file user-B使用bcrypt加密推荐htpasswd -B file user-C costbcrypt 计算强度4~17默认 5htpasswd -BC 10 file user-m使用 MD5 加密默认htpasswd -m file user-5使用 SHA-512 加密htpasswd -5 file user-2使用 SHA-256 加密htpasswd -2 file user加密算法怎么选算法安全性速度推荐场景MD5-m默认一般快内网、临时使用bcrypt-B高较慢生产环境推荐SHA-256-2高中Linux 系统SHA-512-5很高中Linux 系统高安全要求生产环境建议用-BbcryptMD5 在 2026 年真的不够安全了。五、Docker 环境下生成密码文件服务器上没装htpasswd没关系用 Docker 临时容器生成# 方法 1用 httpd 镜像临时生成dockerrun--rmhttpd:alpine htpasswd-nbadmin YourPssw0rd/etc/nginx/conf.d/.htpasswd# 方法 2用 bcrypt 加密dockerrun--rmhttpd:alpine htpasswd-nbBadmin YourPssw0rd/etc/nginx/conf.d/.htpasswd用完即删不占空间。⚠️ 和-b一样密码会留在 shell 历史里docker run ... htpasswd -nb admin YourPssw0rd。命令前加个空格配合HISTCONTROLignorespace或者去掉密码参数改成交互式输入docker run --rm -it httpd:alpine htpasswd -nB admin。六、Nginx 配置 Basic Auth密码文件生成好了接下来配置 Nginx。动手之前先说一件事Basic Auth 必须配 HTTPS否则这把锁是假的。Basic Auth 的凭证是把用户名:密码做Base64 编码塞进Authorization头——Base64 是编码不是加密一眼就能还原。走 HTTP 的话同一个网络里任何人抓个包就拿到了你的明文密码而且是每个请求都带一次。换句话说给公网上的 Grafana 加了 Basic Auth 却跑在http://上你不是把门锁上了只是挂了块请勿入内的牌子还把钥匙贴在门上。下面的示例为了聚焦auth_basic本身都写listen 80实际部署请务必换成 443 证书并把 80 端口重定向过去# 80 只做跳转不承载任何业务 server { listen 80; server_name grafana.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name grafana.example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; location / { auth_basic 请输入账号密码; auth_basic_user_file /etc/nginx/conf.d/.htpasswd; proxy_pass http://localhost:3000; } }证书用 Let’s Encrypt 免费签certbot --nginx一条命令的事没有不配的理由。1. 保护整个站点server { listen 80; server_name grafana.example.com; location / { auth_basic 请输入账号密码; auth_basic_user_file /etc/nginx/conf.d/.htpasswd; proxy_pass http://localhost:3000; } }2. 只保护特定路径server { listen 80; server_name www.example.com; # 公开访问 location / { root /var/www/html; } # 管理后台需要密码 location /admin { auth_basic 管理后台; auth_basic_user_file /etc/nginx/conf.d/.htpasswd; proxy_pass http://localhost:8080; } }3. 某些路径免密如健康检查location /health { auth_basic off; # 关闭认证 proxy_pass http://localhost:8080; }4. 代理后端自带认证时清除 Authorization 头location / { auth_basic 请输入密码; auth_basic_user_file /etc/nginx/conf.d/.htpasswd; proxy_pass http://localhost:10080; # 防止 nginx 的 Basic Auth 凭证被转发给后端 # 后端如果自带认证如 RocketMQ Dashboard会用这个头做二次校验导致 401 proxy_set_header Authorization ; }这个坑很隐蔽Nginxauth_basic验证通过后浏览器发的Authorization: Basic xxx头会被原样转发给后端。如果后端也有认证机制比如 Spring Security就会校验失败返回 401。加一行proxy_set_header Authorization ;即可解决。七、完整实战示例以保护 Grafana 为例从零到一# 1. 生成密码文件bcrypt 加密htpasswd-Bc/etc/nginx/conf.d/.htpasswd admin# 输入密码两次# 2. 追加第二个用户htpasswd-B/etc/nginx/conf.d/.htpasswd ops# 3. 确认文件内容cat/etc/nginx/conf.d/.htpasswd# admin:$2y$05$...# ops:$2y$05$...# 4. 配置 Nginx见上面第六节# 5. 测试 重载nginx-tnginx-sreload# 6. 验证-u 后不写密码回车后交互输入避免密码进 shell 历史curl-uadmin https://grafana.example.com/八、常见问题1. 输入正确密码后仍然 401原因后端服务自带认证Nginx 转发了Authorization头后端校验失败。解决加proxy_set_header Authorization ;见第六节第 4 点。2. 用了-c把其他用户覆盖了解决没救了重新创建。记住-c只在第一次创建文件时用。3. bcrypt 密码 Nginx 不认原因不是 Nginx 版本旧是系统的crypt()不支持 bcrypt。Nginx 自己不实现哈希校验$2y$开头的密码它是直接丢给系统crypt()处理的——glibc 的crypt()不支持 bcrypt而换成 libxcrypt 的发行版Debian 11 / Ubuntu 20.04 / Fedora 等才支持。所以在老 CentOS 7 这类 glibc 系统上Nginx 升到最新版也一样认不了。顺带澄清一个常见误传Nginx 文档里那个1.0.3说的是{SSHA}这类 RFC 2307{scheme}data语法跟 bcrypt 没关系别对着版本号排查。怎么判断先验一下系统支不支持——python3-cimport crypt; print(crypt.crypt(test, $2y$05$abcdefghijklmnopqrstuv))# 输出 $2y$ 开头 支持输出 None 或不以 $2y$ 开头 不支持解决换用支持 libxcrypt 的系统 / 镜像官方nginxDocker 镜像基于 Debian支持 bcrypt或退而求其次用-5SHA-512/-mMD5。4. 密码文件权限问题# 先确认 nginx 以哪个用户跑别照抄组名psaux|grep[n]ginx: worker|awk{print $1}|sort-u# 或看配置grep ^user /etc/nginx/nginx.conf# CentOS / RHEL 默认组是 nginxchownroot:nginx /etc/nginx/conf.d/.htpasswd# Debian / Ubuntu 默认组是 www-datachownroot:www-data /etc/nginx/conf.d/.htpasswdchmod640/etc/nginx/conf.d/.htpasswd⚠️ 组名照抄会直接报chown: invalid group——CentOS 系是nginxDebian 系是www-data先查再改。九、总结场景命令首次创建htpasswd -Bc file user追加用户htpasswd -B file user脚本自动化htpasswd -bB file user passDocker 临时生成docker run --rm httpd:alpine htpasswd -nbB user pass删除用户htpasswd -D file user四句话总结必须配 HTTPS——Basic Auth 是 Base64 编码不是加密走 HTTP 等于明文送密码第一次用-c之后永远不要用-c生产环境用-Bbcrypt但先确认系统crypt()支持glibc 不支持、libxcrypt 才行代理有认证的后端时记得清Authorization头参考资料htpasswd - Apache HTTP Server 官方文档Restricting Access with HTTP Basic Authentication - Nginx 官方文档NGINX Basic Auth with htpasswd: Complete Guide延伸阅读curl 实战程序员必备的接口调试与性能排查利器 —— 加完 Basic Auth用curl -u一条命令就能验证是否生效AI 服务 502 雪崩排查从 Nginx 超时到连接池耗尽查了两次才找到真凶 —— 同样是 Nginx 配置引发的线上故障配错一行就出事️ 标签htpasswdNginxBasic Authbcrypt访问控制Web安全最后更新2026-08-12修正两处事实错误——-C取值范围是4~17非 4~31bcrypt 能否使用取决于系统crypt()实现glibc 不支持、libxcrypt 才支持与 Nginx 版本无关原文「升级 Nginx」的解法在 CentOS 7 上无效。新增 HTTPS 必要性说明Basic Auth 是 Base64 编码不是加密与 443 配置示例chown组名按发行版区分。
返回列表