15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用
09.10.2024

如何在 Ubuntu 上设置 Apache htpasswd 身份验证

Apache的`htpasswd`身份验证提供HTTP基本身份验证——这是一种服务器端访问控制机制,在提供内容之前,会对任何浏览器请求发出用户名/密码提示。它无需任何应用层代码,完全在Apache的模块系统内运行,并在任何PHP、Python或Node.js后端逻辑执行之前在Web服务器层面强制执行。

这使其成为保护预发布环境、内部管理面板、开发构建以及任何必须对公共互联网隐藏的目录的最快、最可靠的方法,而无需部署完整的身份提供商。

htpasswd适用场景与不适用场景

在执行任何命令之前,请先了解威胁模型。HTTP基本身份验证在`Authorization`标头中以Base64编码字符串传输凭据。Base64不是加密——它可以被轻易逆向。这意味着htpasswd身份验证只有在通过HTTPS部署时才是安全的。没有TLS,凭据将以明文形式暴露给任何网络观察者。

适用场景:

  • 预发布和预生产环境
  • 内部开发者工具和仪表板
  • 维护期间临时限制网站访问
  • 在具有自身登录功能的应用程序前添加辅助身份验证层
  • 在服务器层面保护WordPress的`wp-admin`或`xmlrpc.php`

不适用场景:

  • 处理敏感用户数据的面向公众应用程序的主要身份验证
  • 需要审计和记录凭据轮换的环境
  • 需要基于角色的访问控制的多租户系统

如果您的使用场景涉及生产用户账户,请考虑改用OAuth2、LDAP或应用层会话管理。

前提条件

  • 具有root或`sudo`访问权限的Ubuntu 20.04、22.04或24.04服务器
  • 已安装或可通过`apt`安装的Apache 2.4
  • DNS指向您服务器的已注册域名(强烈建议用于SSL)
  • 基本熟悉Linux命令行和文本编辑器

如果您从零开始,VPS托管环境为您提供完整的root访问权限和干净的Ubuntu镜像——这是此配置的理想基础。

第一步:安装Apache2

如果尚未安装Apache,请更新软件包索引并安装:

“`bash

sudo apt update && sudo apt install apache2 -y

“`

验证安装并确认服务正在运行:

“`bash

sudo systemctl status apache2

apache2 -v

“`

启用Apache在重启时自动启动:

“`bash

sudo systemctl enable apache2

“`

Apache的默认文档根目录为`/var/www/html`。主站点配置位于`/etc/apache2/sites-available/000-default.conf`。

第二步:安装apache2-utils软件包

`htpasswd`二进制文件是`apache2-utils`软件包的一部分。在大多数Ubuntu安装中,该软件包与Apache一起安装,但请明确确认其存在:

“`bash

which htpasswd

“`

如果命令没有返回任何内容,请安装该软件包:

“`bash

sudo apt install apache2-utils -y

“`

`apache2-utils`软件包还提供`htdigest`(用于摘要身份验证)、`ab`(用于负载测试的Apache Bench)和`htdbm`(用于DBM格式密码文件)。对于大多数场景,使用默认bcrypt或MD5哈希的`htpasswd`已足够。

第三步:创建.htpasswd文件并添加用户

选择密码哈希算法

这是原始文档几乎普遍忽略的细节。`htpasswd`工具支持多种哈希方案,选择哪种方案具有实际的安全影响:

算法标志安全级别备注
———–—————————-
bcrypt`-B`推荐;设计上计算成本较高
SHA-256/512 (apr1-md5)`-m`中等大多数Linux系统的默认值;可接受
MD5(旧版)某些构建版本上的`-m`不要用于新部署
明文`-p`切勿在生产环境中使用
SHA-1`-s`已弃用;易受暴力破解攻击

创建新的`.htpasswd`文件时始终使用bcrypt:

“`bash

sudo htpasswd -cB /etc/apache2/.htpasswd your_username

“`

标志说明:

  • `-c` — 创建新文件。重要警告:如果文件已存在,`-c`会静默覆盖它,删除所有现有用户。只在首次创建文件时使用`-c`。
  • `-B` — 强制使用bcrypt哈希
  • `/etc/apache2/.htpasswd` — 目标文件路径,有意置于Web根目录之外
  • `your_username` — 替换为实际用户名

系统将提示您输入并确认密码。生成的文件条目如下所示:

“`

your_username:$2y$05$randomsaltandhashedpasswordstring

“`

添加其他用户

要向现有文件添加更多用户,请省略`-c`标志:

“`bash

sudo htpasswd -B /etc/apache2/.htpasswd second_user

sudo htpasswd -B /etc/apache2/.htpasswd third_user

“`

删除用户

“`bash

sudo htpasswd -D /etc/apache2/.htpasswd username_to_remove

“`

验证文件内容

“`bash

sudo cat /etc/apache2/.htpasswd

“`

每行以`username:hashed_password`格式表示一个用户。

第四步:配置Apache密码保护

应用htpasswd身份验证有两种方法:通过`.htaccess`文件或直接在虚拟主机配置中。每种方法在性能和维护方面都有明显的差异。

方法比较

因素.htaccess方法虚拟主机配置方法
——–—————–—————————
需要重启Apache
性能影响较高(Apache每次请求都会读取)较低(启动时加载一次)
粒度按目录,委托式集中在配置文件中
推荐用于共享主机、动态按目录配置具有root访问权限的独立/VPS服务器
安全态势略弱(文件必须可被Web进程读取)更强(配置不可通过Web访问)

在您拥有完整root访问权限的独立服务器或VPS上,虚拟主机配置方法在性能和可维护性方面始终更为优选。

选项1:使用.htaccess文件

此方法需要为目标目录启用`AllowOverride`。首先,编辑站点配置:

“`bash

sudo nano /etc/apache2/sites-available/000-default.conf

“`

找到或添加Web根目录的`<Directory>`块,并设置`AllowOverride All`:

“`apache

<VirtualHost *:80>

ServerAdmin webmaster@localhost

DocumentRoot /var/www/html

<Directory /var/www/html>

AllowOverride All

Options -Indexes +FollowSymLinks

Require all granted

</Directory>

</VirtualHost>

“`

重启Apache以应用配置更改:

“`bash

sudo systemctl restart apache2

“`

现在在您要保护的目录中创建`.htaccess`文件:

“`bash

sudo nano /var/www/html/.htaccess

“`

添加以下身份验证指令:

“`apache

AuthType Basic

AuthName "Restricted Access — Authorized Personnel Only"

AuthUserFile /etc/apache2/.htpasswd

Require valid-user

“`

指令说明:

  • `AuthType Basic` — 激活HTTP基本身份验证。替代方案是`Digest`,它避免以Base64发送凭据,但存在更广泛的兼容性问题。
  • `AuthName` — 浏览器登录对话框中显示的领域字符串。使其足够具有描述性,让合法用户了解他们正在访问的内容。
  • `AuthUserFile` — `.htpasswd`文件的绝对路径。必须可被Apache进程用户(`www-data`)读取。
  • `Require valid-user` — 授予`.htpasswd`文件中任何用户的访问权限。您可以使用`Require user alice bob`进一步限制,只允许特定账户访问。

保存并关闭文件。无需重启Apache——`.htaccess`更改立即生效。

选项2:直接虚拟主机配置(推荐)

这是生产级方法。直接编辑虚拟主机配置文件:

“`bash

sudo nano /etc/apache2/sites-available/000-default.conf

“`

在`<VirtualHost>`块内添加带有身份验证指令的`<Directory>`块:

“`apache

<VirtualHost *:80>

ServerAdmin webmaster@localhost

DocumentRoot /var/www/html

ServerName yourdomain.com

<Directory "/var/www/html/protected">

AuthType Basic

AuthName "Internal Tools"

AuthUserFile /etc/apache2/.htpasswd

Require valid-user

Options -Indexes

</Directory>

</VirtualHost>

“`

注意使用`/var/www/html/protected`而非整个Web根目录。在实践中,将身份验证范围限定到子目录更为常见——您保护`/admin`、`/staging`或`/api-docs`,同时保持公共站点可访问。

在重启之前验证配置语法:

“`bash

sudo apachectl configtest

“`

您应该看到`Syntax OK`。如果有错误,Apache会精确描述它们。在生产环境中,切勿在未通过此检查的情况下重启Apache。

重启Apache:

“`bash

sudo systemctl restart apache2

“`

保护特定文件类型而非目录

一种鲜为人知但非常实用的模式是使用`<FilesMatch>`来限制对特定文件扩展名的访问,而不是整个目录:

“`apache

<FilesMatch ".(env|log|sql|bak)$">

AuthType Basic

AuthName "Restricted Files"

AuthUserFile /etc/apache2/.htpasswd

Require valid-user

</FilesMatch>

“`

这对于阻止直接访问Web根目录中可能因历史原因存在的`.env`文件、数据库转储或日志文件特别有用。

第五步:上线前启用SSL

如前所述,通过普通HTTP的HTTP基本身份验证是不安全的。在将任何受htpasswd保护的资源暴露到互联网之前,请强制使用HTTPS。

安装Certbot以获取Let’s Encrypt证书:

“`bash

sudo apt install certbot python3-certbot-apache -y

sudo certbot –apache -d yourdomain.com

“`

Certbot将自动修改您的Apache配置,将HTTP重定向到HTTPS并安装证书。或者,您可以通过SSL证书为需要扩展验证或通配符覆盖的域名申请商业证书。

启用SSL后,在HTTP虚拟主机中添加HTTPS重定向:

“`apache

<VirtualHost *:80>

ServerName yourdomain.com

Redirect permanent / https://yourdomain.com/

</VirtualHost>

“`

第六步:加固.htpasswd文件权限

`.htpasswd`文件包含哈希凭据。尽管bcrypt哈希在计算上破解成本很高,但该文件必须在文件系统层面受到保护。

将所有权设置为Apache进程用户并限制读取权限:

“`bash

sudo chown root:www-data /etc/apache2/.htpasswd

sudo chmod 640 /etc/apache2/.htpasswd

“`

此配置意味着:

  • `root`拥有该文件并可读写
  • `www-data`(Apache进程)可以读取它
  • 所有其他用户无访问权限

验证权限:

“`bash

ls -la /etc/apache2/.htpasswd

“`

预期输出:

“`

-rw-r—– 1 root www-data 89 Jan 15 10:23 /etc/apache2/.htpasswd

“`

阻止直接Web访问.htpasswd

如果`.htpasswd`文件因任何原因位于Web根目录内,请在Apache配置或`.htaccess`中添加明确的拒绝规则:

“`apache

<Files ".htpasswd">

Require all denied

</Files>

“`

这是一种纵深防御措施。该文件永远不应位于Web根目录内,但此规则确保即使它在那里,Apache也会返回403禁止响应而不是提供该文件。

第七步:测试身份验证

打开浏览器并导航到受保护的URL:

“`

http://your_server_ip_or_domain/protected/

“`

您应该看到浏览器原生身份验证对话框。输入您使用`htpasswd`创建的凭据。身份验证成功则授予访问权限;凭据不正确则返回HTTP 401未授权响应。

从命令行测试

使用`curl`在不使用浏览器的情况下验证身份验证行为:

“`bash

Test with correct credentials — should return 200 OK

curl -u your_username:your_password -I http://yourdomain.com/protected/

Test without credentials — should return 401 Unauthorized

curl -I http://yourdomain.com/protected/

Test with wrong credentials — should return 401 Unauthorized

curl -u your_username:wrongpassword -I http://yourdomain.com/protected/

“`

这在CI/CD管道或自动化监控脚本中特别有用,您需要在部署后验证身份验证是否正确执行。

高级配置模式

将htpasswd与基于IP的访问控制结合

您可以使用`RequireAll`或`RequireAny`块将密码身份验证与IP白名单结合:

“`apache

<Directory "/var/www/html/admin">

AuthType Basic

AuthName "Admin Panel"

AuthUserFile /etc/apache2/.htpasswd

Allow access if EITHER condition is met

<RequireAny>

Require ip 192.168.1.0/24

Require valid-user

</RequireAny>

</Directory>

“`

或同时要求两个条件(IP必须匹配且凭据必须有效):

“`apache

<RequireAll>

Require ip 203.0.113.0/24

Require valid-user

</RequireAll>

“`

此模式对管理面板非常有效:内部网络用户获得密码提示访问,而外部IP无论凭据如何都被完全阻止。

限制身份验证尝试速率

HTTP基本身份验证没有内置的暴力破解保护。使用`mod_evasive`或`fail2ban`来缓解此问题:

“`bash

sudo apt install fail2ban -y

“`

在`/etc/fail2ban/filter.d/apache-auth.conf`为Apache身份验证失败创建自定义Fail2ban过滤器:

“`ini

[Definition]

failregex = ^<HOST> -.*"(GET|POST|HEAD).*" 401

ignoreregex =

“`

在`/etc/fail2ban/jail.local`添加jail配置:

“`ini

[apache-auth]

enabled = true

port = http,https

filter = apache-auth

logpath = /var/log/apache2/access.log

maxretry = 5

bantime = 3600

findtime = 600

“`

重启Fail2ban:

“`bash

sudo systemctl restart fail2ban

“`

这会封禁在十分钟内产生五次401响应的任何IP,封禁时长为一小时——对自动化凭据填充攻击具有显著的威慑作用。

使用Location块进行基于URL的保护

对于受保护内容从特定URL路径而非文件系统目录提供的应用程序,请使用`<Location>`而非`<Directory>`:

“`apache

<Location "/api/internal">

AuthType Basic

AuthName "Internal API"

AuthUserFile /etc/apache2/.htpasswd

Require user api_user service_account

</Location>

“`

注意使用带有特定用户名的`Require user`而非`Require valid-user`——即使`.htpasswd`文件包含其他用户,这也将端点限制为仅这两个账户。

实用决策矩阵

使用此矩阵确定适合您场景的正确配置方法:

场景推荐方法
———-———————
保护VPS上的预发布子目录使用bcrypt的虚拟主机`<Directory>`块
无Apache配置访问权限的共享主机`.htaccess`方法
仅从办公室IP可访问的管理面板结合IP + valid-user的`RequireAll`
阻止Web根目录中的`.env`和`.sql`文件带`Require all denied`的`<FilesMatch>`
需要对一个路径进行身份验证的高流量站点虚拟主机配置中的`<Location>`块
任何面向公众的受保护资源强制SSL + htpasswd + Fail2ban

关键技术要点

  • 创建`.htpasswd`文件时始终使用bcrypt(`-B`标志)。旧版MD5和SHA-1哈希可被现代GPU硬件在数秒内破解。
  • 切勿在任何可从互联网访问的环境中通过HTTP部署htpasswd。基本身份验证凭据的Base64编码不提供任何保密性。
  • 在任何具有root访问权限的服务器上,优先选择虚拟主机配置而非`.htaccess`。在负载下性能差异是可测量的,因为Apache对每个请求都会重新读取`.htaccess`文件。
  • 将保护范围限定到最小必要的目录或URL路径。当只有`/var/www/html/admin`需要保护时,保护整个`/var/www/html`会增加不必要的摩擦。
  • 将`.htpasswd`权限设置为`640`,所有权为`root:www-data`。该文件永远不应对所有人可读。
  • 实施Fail2ban以防止暴力破解攻击。HTTP基本身份验证没有原生的速率限制或账户锁定机制。
  • 在生产环境中每次重启前使用`apachectl configtest`验证Apache配置。
  • 将htpasswd与您的域名基础设施配对。正确配置的带有DNS和SSL的域名是基础——通过域名注册管理您的域名,将所有基础设施组件置于同一提供商下。

对于管理多个受保护环境的团队,带cPanel的VPS提供图形界面来管理密码保护目录,无需直接命令行访问,这可以减少技术能力较弱团队的配置错误。

常见问题

htpasswd身份验证是否适用于所有浏览器?

是的。HTTP基本身份验证在RFC 7617中定义,所有现代浏览器均支持,包括Chrome、Firefox、Safari和Edge。移动浏览器也支持它。原生浏览器对话框的外观因浏览器和操作系统而异,但底层协议行为是相同的。

如果Apache配置中的.htpasswd文件路径错误会发生什么?

Apache将对受保护资源的任何请求返回500内部服务器错误,并在`/var/log/apache2/error.log`中记录类似`Could not open password file: /path/to/.htpasswd`的错误。请始终验证绝对路径是否正确,以及`www-data`用户是否具有该文件的读取权限。

我可以使用htpasswd保护WordPress站点的管理区域吗?

可以,这是推荐的加固实践。为`/wp-admin/`添加htpasswd保护并限制对`xmlrpc.php`的访问,在WordPress自身登录逻辑执行之前添加服务器级身份验证层,阻止从未到达PHP的自动化机器人和暴力破解脚本。为获得更好的性能,请在虚拟主机中将其配置为`<Directory>`块,而非`.htaccess`。

如何更新现有.htpasswd文件中用户的密码?

运行不带`-c`标志的`htpasswd`并指定现有用户名:`sudo htpasswd -B /etc/apache2/.htpasswd existing_user`。系统将提示您输入新密码。该命令只覆盖该用户的条目,其他所有用户保持不变。

.htpasswd文件中可以存储的用户数量有限制吗?

Apache没有强制规定硬性限制。但是,由于Apache对每个身份验证请求都对文件进行线性扫描,文件非常大时性能会明显下降——通常超过几百个用户。对于需要为数十或数百个用户进行身份验证的环境,请考虑使用带数据库后端的`mod_authn_dbd`,或通过`mod_authnz_ldap`进行LDAP身份验证,这些方案专为规模化设计。

15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用