关于 htpasswd 条目生成
htpasswd 条目生成器为 Apache 风格的口令文件产出一行「用户名 + 哈希」,可以使用你指定成本因子的 bcrypt,也可以使用面向老旧服务器的 SHA-1 格式。它产出的是校验值,不是被保存下来的密码。
HTTP 基本认证会在每个请求上把用户名和密码用 Base64 编码后发送,服务端再与口令文件里的哈希比对。Base64 是编码不是加密,所以只要连接不是 TLS,这份凭据就等同于明文。口令文件所能保护的一切压在两件事上:链路上的 HTTPS,以及足够慢的哈希,让文件被偷走也不会立刻交出密码。
如何使用这个开发者工具
- 填写用户名。冒号和换行会被拒绝,因为冒号是字段分隔符,换行是记录分隔符。
- 选择算法:当下的部署一律用 bcrypt,只有当服务器或设备不接受 bcrypt 时才用 SHA-1。
- 使用 bcrypt 时设置成本因子,范围 4 到 14。每加一档计算量翻倍,10 到 12 是常规区间。
- 输入密码并生成,把这一行追加到口令文件中,每行一条。
- 确认文件位于站点根目录之外、且只有服务进程用户可读,然后用 HTTPS 请求实测一次。
实例:同一份凭据的两种格式
同一个用户名和密码,各生成一次。两行编码的是同一个密钥,却毫无相似之处——这正是加盐的意义所在。
用户名 deploy
密码 deploy-2026bcrypt,成本 10
deploy:$2b$10$psTmXzHmSI/IhQ.trTEN0eoHZGy8M3nyJfsUcyu/Ny6pixaQ.kRdm
SHA-1
deploy:{SHA}U1MgtpXcK2GlT6IpcBGpgFSU2Ac=bcrypt 字段可以从左往右读:变体、成本因子,然后是 22 个字符的编码盐值和 31 个字符的哈希,总长 60。再生成一次字符串完全不同,因为盐是新的,但两者都能验证通过。SHA-1 那一行没有盐,同一个密码永远产出这一个值。
口令文件的各种格式及其现状
本工具写出的是第一行和第三行。其余几种会出现在你接手的老文件里,认出前缀通常是判断眼前是什么东西的最快办法。
| 格式 | 前缀 | 盐 | 现状 |
|---|---|---|---|
| bcrypt | $2y$、$2a$ 或 $2b$ | 128 位,内嵌 | 推荐,成本可调。Apache 2.4.4 及以后版本与 nginx 支持 |
| Apache MD5 | $apr1$ | 48 位 | 遗留的默认格式。1000 轮 MD5,在今天远远不够慢 |
| SHA-1 | {SHA} | 无 | 单次无盐哈希。作为口令存储已被攻破,仅用于兼容 |
| crypt(DES) | 13 个字符,无前缀 | 12 位 | 已废弃。会把密码截断到 8 个字符;仅 Unix 构建 |
| 明文 | 密码本身 | 无 | 只在部分非 Unix 的 Apache 构建上支持过。绝不可接受 |
常见问题排查
条目看起来没问题,但服务器拒绝所有密码。
成因 这个 Apache 构建不支持 bcrypt。该支持在 2.4.4 引入,一些设备和老旧发行版包至今没有带上它,于是 bcrypt 那一行永远匹配不上。
解决办法 先确认服务器实际运行的版本。无法升级就退回 SHA-1,并在端点前面加一层 IP 白名单——单靠这个格式提供不了多少保护。
这里生成的是 $2b$,而服务器自带的 htpasswd -B 写出来的是 $2y$。
成因 前缀记录的是产出该哈希的 bcrypt 变体。2a、2b、2y 的差别仅在于如何处理一个 8 位字符的历史编码缺陷,Apache 的 crypt_blowfish 三种都能验证。
解决办法 对 Apache 和 nginx 无需任何处理。若下游检查器坚持要 $2y$,请用服务器自带的 htpasswd -B 重新生成,不要手工改前缀。
条目在 Shell 里可用,放进配置文件或 Compose 变量就坏了。
成因 bcrypt 哈希里全是美元符,而在 Shell、Docker Compose 插值以及许多模板系统中,美元符表示变量引用,于是这个值会悄悄变短。
解决办法 在 Shell 中用单引号包住;在 Compose 文件里把每个美元符写成两个;更好的做法是直接挂载口令文件,而不是让哈希经过环境变量。
认证很慢,或者服务器在压力下卡住。
成因 bcrypt 的成本是指数级的,成本 14 的计算量是成本 10 的十六倍。基本认证没有会话,服务端每个请求都要重新验证一次。
解决办法 高请求量的端点把成本控制在 10 到 12;确实需要更高因子时,请在它前面加一层会话或令牌机制。
适合用这个工具的场景
- 用尽可能少的配置保护一个预发站点、内部看板或指标端点。
- 为 nginx 的 auth_basic_user_file 生成条目,它读的是同一种格式。
- 在无法运行 htpasswd 命令的环境里添加用户,例如托管平台或镜像构建步骤。
- 在敲定成本因子之前,直观看到调整 bcrypt 成本对生成结果的影响。
应该换用别的工具的场景
- 承载真实用户账号。这里没有注册、重置、锁定,撤销一个凭据还必须手工改文件。这类需求请用身份提供方。
- 保护走明文 HTTP 的任何东西。Authorization 头是可逆的 Base64,真正让密码在传输中保持私密的只有 TLS。
- 为你自己应用的用户表生成 bcrypt 哈希。这里产出的是 Apache 格式的键值对——只取哈希那一段,并先确认框架期望的成本和变体。
隐私与数据处理
哈希在当前标签页内完成:bcrypt 由打包进页面的 JavaScript 实现计算,SHA-1 由浏览器的 WebCrypto 计算。用户名和密码都不会被发送,密码框已做标记,浏览器不会提示保存它。但对任何输入进网页的密钥,建议都一样:这里用一次性密码,正式条目请在服务器上用 htpasswd 命令生成。
相关开发者工具
常见问题
成本因子该选多少?
在将要运行它的机器上,选验证耗时仍可接受的最高成本,通常 50 到 250 毫秒,典型硬件上对应 10 到 12。基本认证是每个请求都付一次这个代价,而不是每个会话付一次。
能从条目反推出密码吗?
不能,bcrypt 没有逆运算。持有文件的人只能猜:用该行记录的盐和成本对候选密码做哈希再比对。成本、密码长度和文件权限要一起看。
为什么每次生成的 bcrypt 行都不一样?
每个哈希内嵌一个新的随机盐,因此同一个密码每次生成的字符串都不同,且全都能验证通过。SHA-1 格式弱就弱在缺少这个性质:相同密码产出相同条目。
SHA-1 格式还有能用的场合吗?
只有在对接确实做不到更好的系统时,而且必须配合另一层控制,例如 IP 白名单或 VPN。它就是一次无盐哈希,现代硬件对它的暴力破解速率高得惊人。
nginx 认这个文件吗?
认。auth_basic_user_file 读的是同一种格式,支持 bcrypt、SHA-1 形式、Apache MD5 和 crypt。真正容易不同的是路径以及工作进程以哪个用户身份运行,所以先查权限。
文件该放在哪里,能放多个用户吗?
放在站点根目录之外,属主为 root,服务进程用户可读,权限 640 或更严——一个 .htpasswd 被当作静态资源对外提供,就是一次性丢光全部凭据。一个文件可以放多个用户,每人一行。