Apache HTTP 服务器版本 2.4
身份验证和授权过程中涉及三种类型的模块。您通常需要从每个组中选择至少一个模块。
AuthType
指令)
AuthBasicProvider
和 AuthDigestProvider
指令)
Require
指令)
除了这些模块之外,还有 mod_authn_core
和 mod_authz_core
。这些模块实现了对所有身份验证模块都至关重要的核心指令。
模块 mod_authnz_ldap
既是身份验证提供程序,也是授权提供程序。模块 mod_authz_host
基于主机名、IP 地址或请求特征提供授权和访问控制,但不是身份验证提供程序系统的一部分。为了与 mod_access 向后兼容,有一个新的模块 mod_access_compat
。
您可能还想查看 访问控制 操作指南,其中讨论了控制对服务器访问的各种方法。
如果您网站上有一些敏感信息或仅供一小部分人使用,本文中的技术将帮助您确保看到这些页面的人是您想要看到他们的人。
本文介绍了保护网站部分的“标准”方法,大多数人都会使用这种方法。
如果您的数据确实需要安全,请考虑使用 mod_ssl
以及任何身份验证。
本文中讨论的指令需要放在您的主服务器配置文件(通常位于 <Directory>
部分)中,或者放在每个目录的配置文件(.htaccess
文件)中。
如果您打算使用 .htaccess
文件,则需要有一个服务器配置,允许在这些文件中放置身份验证指令。这是通过 AllowOverride
指令完成的,该指令指定哪些指令(如果有)可以放在每个目录的配置文件中。
由于我们在这里讨论的是身份验证,因此您将需要一个类似于以下内容的 AllowOverride
指令
AllowOverride AuthConfig
或者,如果您只是将指令直接放在主服务器配置文件中,那么您当然需要对该文件具有写入权限。
您还需要了解服务器目录结构的一些知识,以便知道某些文件的位置。这应该不会太难,当我们谈到这一点时,我会尽量说清楚。
您还需要确保模块 mod_authn_core
和 mod_authz_core
已经构建到 httpd 二进制文件中或由 httpd.conf 配置文件加载。这两个模块都提供了对 Web 服务器中身份验证和授权的配置和使用至关重要的核心指令和功能。
以下是保护服务器上目录密码的基本步骤。
首先,您需要创建一个密码文件。具体操作方法将根据您选择的身份验证提供程序而有所不同。稍后将详细介绍。首先,我们将使用文本密码文件。
此文件应放置在 Web 无法访问的位置。这样可以防止人们下载密码文件。例如,如果您的文档是从 /usr/local/apache/htdocs
提供的,您可能希望将密码文件放在 /usr/local/apache/passwd
中。
要创建文件,请使用随 Apache 附带的 htpasswd
实用程序。它将位于您安装 Apache 的 bin
目录中。如果您从第三方软件包安装了 Apache,它可能位于您的执行路径中。
要创建文件,请键入
htpasswd -c /usr/local/apache/passwd/passwords rbowen
htpasswd
将提示您输入密码,然后再次提示您输入密码以确认。
# htpasswd -c /usr/local/apache/passwd/passwords rbowen
新密码: mypassword
重新输入新密码: mypassword
正在为用户 rbowen 添加密码
如果 htpasswd
不在您的路径中,您当然需要键入文件的完整路径才能运行它。在默认安装中,它位于 /usr/local/apache2/bin/htpasswd
接下来,您需要配置服务器以请求密码并告诉服务器哪些用户可以访问。您可以通过编辑 httpd.conf
文件或使用 .htaccess
文件来完成此操作。例如,如果您希望保护目录 /usr/local/apache/htdocs/secret
,您可以使用以下指令,这些指令可以放在文件 /usr/local/apache/htdocs/secret/.htaccess
中,也可以放在 httpd.conf
中的 <Directory "/usr/local/apache/htdocs/secret"> 部分中。
AuthType Basic AuthName "Restricted Files" # (Following line optional) AuthBasicProvider file AuthUserFile "/usr/local/apache/passwd/passwords" Require user rbowen
让我们分别检查每个指令。 AuthType
指令选择用于验证用户的方法。最常见的方法是 Basic
,这是由 mod_auth_basic
实现的方法。但是,必须注意,基本身份验证会将密码从客户端发送到服务器,而不进行加密。因此,此方法不应用于高度敏感的数据,除非与 mod_ssl
结合使用。Apache 支持另一种身份验证方法:AuthType Digest
。此方法由 mod_auth_digest
实现,旨在更安全。但现在情况不再如此,连接应使用 mod_ssl
进行加密。
AuthName
指令设置身份验证中使用的 领域。领域有两个主要功能。首先,客户端通常将此信息作为密码对话框的一部分呈现给用户。其次,它由客户端用于确定为给定身份验证区域发送哪个密码。
因此,例如,一旦客户端在 "Restricted Files"
区域中进行了身份验证,它将自动为同一服务器上标记为 "Restricted Files"
领域的任何区域重试相同的密码。因此,您可以通过让多个受限区域共享同一个领域来防止用户被多次提示输入密码。当然,出于安全原因,每当服务器主机名更改时,客户端都需要再次询问密码。
AuthBasicProvider
在这种情况下是可选的,因为 file
是此指令的默认值。如果您选择其他身份验证来源,例如 mod_authn_dbm
或 mod_authn_dbd
,则需要使用此指令。
AuthUserFile
指令设置我们刚刚使用 htpasswd
创建的密码文件的路径。如果您有大量用户,在每次请求时搜索纯文本文件以验证用户身份可能会非常慢。Apache 还能够将用户信息存储在快速数据库文件中。 mod_authn_dbm
模块提供 AuthDBMUserFile
指令。可以使用 dbmmanage
和 htdbm
程序创建和操作这些文件。第三方模块提供了许多其他类型的身份验证选项。
最后, Require
指令通过设置允许访问服务器此区域的用户来提供授权部分。在下一节中,我们将讨论使用 Require
指令的各种方法。
上面的指令只允许一个人(具体来说是用户名为 rbowen
的人)进入目录。在大多数情况下,您希望允许多个人进入。这就是 AuthGroupFile
的作用。
如果你想让多个人进入,你需要创建一个组文件,将组名与该组中的用户列表关联起来。这个文件的格式很简单,你可以用你喜欢的编辑器创建它。文件的内容看起来像这样
GroupName: rbowen dpitts sungo rshersey
这只是一行用空格分隔的组成员列表。
要将用户添加到已有的密码文件中,输入
htpasswd /usr/local/apache/passwd/passwords dpitts
你会得到和之前一样的响应,但它会被追加到现有文件中,而不是创建一个新文件。(是-c
让它创建了一个新的密码文件)。
现在,你需要修改你的.htaccess
文件或<Directory>
块,使其看起来像下面这样
AuthType Basic AuthName "By Invitation Only" # Optional line: AuthBasicProvider file AuthUserFile "/usr/local/apache/passwd/passwords" AuthGroupFile "/usr/local/apache/passwd/groups" Require group GroupName
现在,任何在GroupName
组中列出,并且在password
文件中拥有条目的人,只要输入正确的密码,就可以进入。
还有另一种方法可以允许多个用户进入,这种方法不太具体。与其创建组文件,不如直接使用以下指令
Require valid-user
使用它而不是Require user rbowen
行将允许任何在密码文件中列出,并且正确输入密码的人进入。
由于基本身份验证的指定方式,每次你从服务器请求文档时,你的用户名和密码都必须经过验证。即使你正在重新加载同一个页面,并且页面上的每个图像(如果它们来自受保护的目录)也是如此。可以想象,这会稍微减慢速度。减慢速度的程度与密码文件的大小成正比,因为它必须打开那个文件,并一直向下遍历用户列表,直到找到你的名字。而且它必须在每次页面加载时都这样做。
这样做的一个后果是,在一个密码文件中可以放入的用户数量存在实际限制。这个限制会根据你特定服务器机器的性能而有所不同,但你可以预期,一旦超过几百个条目,就会出现速度变慢的情况,此时你可能需要考虑使用其他身份验证方法。
由于将密码存储在纯文本文件中存在上述问题,你可能希望将密码存储在其他地方,例如数据库中。
mod_authn_dbm
和mod_authn_dbd
是两个使这成为可能的模块。与其选择
,不如选择AuthBasicProvider
filedbm
或dbd
作为你的存储格式。
例如,要选择dbm文件而不是文本文件
<Directory "/www/docs/private"> AuthName "Private" AuthType Basic AuthBasicProvider dbm AuthDBMUserFile "/www/passwords/passwd.dbm" Require valid-user </Directory>
还有其他选项可用。请参阅mod_authn_dbm
文档以了解更多详细信息。
随着新的基于提供者的身份验证和授权架构的引入,你不再局限于单一的身份验证或授权方法。事实上,任何数量的提供者都可以混合和匹配,以提供完全满足你需求的方案。在下面的示例中,文件和基于LDAP的身份验证提供者都被使用。
<Directory "/www/docs/private"> AuthName "Private" AuthType Basic AuthBasicProvider file ldap AuthUserFile "/usr/local/apache/passwd/passwords" AuthLDAPURL ldap://ldaphost/o=yourorg Require valid-user </Directory>
在这个示例中,文件提供者将首先尝试验证用户。如果它无法验证用户,则将调用LDAP提供者。这允许在你的组织实施多种身份验证存储时,扩大身份验证的范围。其他身份验证和授权场景可能包括将一种身份验证类型与另一种授权类型混合使用。例如,针对密码文件进行身份验证,但针对LDAP目录进行授权。
就像可以实现多个身份验证提供者一样,也可以使用多个授权方法。在这个示例中,同时使用了文件组授权和LDAP组授权。
<Directory "/www/docs/private"> AuthName "Private" AuthType Basic AuthBasicProvider file AuthUserFile "/usr/local/apache/passwd/passwords" AuthLDAPURL ldap://ldaphost/o=yourorg AuthGroupFile "/usr/local/apache/passwd/groups" Require group GroupName Require ldap-group cn=mygroup,o=yourorg </Directory>
为了进一步进行授权,授权容器指令,例如<RequireAll>
和<RequireAny>
,允许应用逻辑,以便可以完全通过配置控制处理授权的顺序。请参阅授权容器,了解如何应用它们的示例。
现在,授权的应用方式比仅仅针对单个数据存储进行单次检查要灵活得多。现在可以控制授权的执行方式和顺序。
过去,控制授权的应用方式和顺序一直是一个谜。在Apache 2.2中,引入了基于提供者的身份验证机制,以将实际的身份验证过程与授权和支持功能分离。其中一个附带的好处是,身份验证提供者可以按特定顺序进行配置和调用,而这并不依赖于auth模块本身的加载顺序。这种基于提供者的相同机制也已应用于授权。这意味着Require
指令不仅指定了要使用哪些授权方法,还指定了调用它们的顺序。多个授权方法按Require
指令在配置中出现的顺序调用。
随着授权容器指令(如<RequireAll>
和<RequireAny>
)的引入,配置还可以控制何时调用授权方法以及哪些标准决定何时授予访问权限。请参阅授权容器,了解如何使用它们来表达复杂的授权逻辑的示例。
默认情况下,所有Require
指令都将被视为包含在<RequireAny>
容器指令中。换句话说,如果任何指定的授权方法成功,则授予授权。
通过用户名和密码进行身份验证只是故事的一部分。通常,你希望根据除用户身份之外的其他因素来允许人们进入。例如,他们来自哪里。
授权提供者all
、env
、host
和ip
允许你根据其他基于主机的标准(如请求文档的机器的主机名或IP地址)来允许或拒绝访问。
这些提供者的使用方式通过Require
指令指定。此指令注册将在请求处理的授权阶段调用的授权提供者。例如
Require ip address
其中address是一个IP地址(或部分IP地址),或者
Require host domain_name
其中domain_name是一个完全限定的域名(或部分域名);如果需要,你可以提供多个地址或域名。
例如,如果你有人在你的留言板发布垃圾信息,并且你想阻止他们,你可以执行以下操作
<RequireAll> Require all granted Require not ip 10.252.46.165 </RequireAll>
来自该地址的访问者将无法看到此指令涵盖的内容。如果相反,你有一个机器名,而不是一个IP地址,你可以使用它。
<RequireAll> Require all granted Require not host host.example.com </RequireAll>
而且,如果你想阻止来自整个域的访问,你可以只指定地址或域名的一部分
<RequireAll> Require all granted Require not ip 192.168.205 Require not host phishers.example.com moreidiots.example Require not host ke </RequireAll>
使用<RequireAll>
和多个<Require>
指令,每个指令都用not
否定,将只允许在所有否定条件都为真的情况下访问。换句话说,如果任何否定条件失败,访问将被阻止。
采用基于提供者的身份验证机制的一个副作用是,以前的访问控制指令Order
、Allow
、Deny
和Satisfy
不再需要。但是,为了提供对旧配置的向后兼容性,这些指令已移至mod_access_compat
模块。
mod_access_compat
提供的指令已被mod_authz_host
弃用。将旧指令(如Order
、Allow
或Deny
)与新指令(如Require
)混合使用在技术上是可行的,但不建议这样做。mod_access_compat
模块是为了支持仅包含旧指令的配置而创建的,以便促进2.4升级。请查看升级指南以了解更多信息。
有时,身份验证会对提供者或你的网络造成不可接受的负载。这最有可能影响mod_authn_dbd
(或第三方/自定义提供者)的用户。为了解决这个问题,HTTPD 2.3/2.4 引入了一个新的缓存提供者mod_authn_socache
,用于缓存凭据并减少对源提供者的负载。
这可能会为某些用户提供显著的性能提升。
你还应该阅读mod_auth_basic
和mod_authz_host
的文档,其中包含有关所有这些工作原理的更多信息。指令<AuthnProviderAlias>
也可以帮助简化某些身份验证配置。
Apache 支持的用于身份验证数据的各种密码在密码加密中进行了说明。
你可能还想查看访问控制指南,其中讨论了几个相关主题。