Apache认证和授权
身份验证是验证访问者是否是他们所声称的人的任何过程。授权是允许访问者进入他们想去的地方或获得他们想要的信息的过程。
如果您的网站上的信息仅对一小部分人使用,下面这些技巧将帮助您确保看到这些网页的人员是您想要查看的人。
本文还将介绍保护大多数人将要使用的网站部分的“标准”方法。
1. 前提条件
本文中讨论的指令需要在主服务器配置文件(通常在<Directory>
部分中)或每目录配置文件(.htaccess
文件)中。
如果计划使用.htaccess
文件,则需要具有允许在这些文件中放置身份验证指令的服务器配置。这是通过AllowOverride
指令完成的,该指令指定可以在每个目录配置文件中放入哪些指令(如果有)。
由于我们在这里谈论身份验证,所以需要如下所示的AllowOverride
指令:
AllowOverride AuthConfig
或者,如果您只是将指令直接放在主服务器配置文件中,需要具有该文件的写入权限。
并且您需要了解服务器的目录结构,以便了解某些文件的保存位置。这应该不是非常困难,当到达那一点时,我们会尽力说清楚。
还需要确保模块mod_authn_core
和mod_authz_core
已内置到httpd二进制文件中或由httpd.conf
配置文件加载。这两个模块都提供核心指令和功能,这些指令和功能对于在Web服务器中配置和使用身份验证和授权至关重要。
2. 配置工作
以下是密码保护服务器上目录的基础知识。
首先,您需要创建一个密码文件。具体如何执行此操作将取决于您选择的身份验证提供程序。稍后会详细介绍。首先,我们将使用文本密码文件。
此文件应放置在无法从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
New password: mypassword
Re-type new password: mypassword
Adding password for user 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
指令设置要在身份验证中使用的Realm
。领域有两个主要功能。首先,客户端经常将此信息作为密码对话框的一部分呈现给用户。其次,客户端使用它来确定为给定的已验证区域发送的密码。
因此,一旦客户端在“受限文件”区域中进行了身份验证,它将自动为同一服务器上标有“受限文件”域的任何区域重试相同的密码。因此,通过让多个受限区域共享同一个域,可以防止用户多次提示输入密码。当然,出于安全原因,只要服务器的主机名发生更改,客户端就始终需要再次询问密码。
在这种情况下,AuthBasicProvider
是可选的,因为file
是此指令的默认值。如果要为身份验证选择其他源,则需要使用此指令,例如mod_authn_dbm
或mod_authn_dbd
。
AuthUserFile
指令设置htpasswd
创建的密码文件的路径。如果需要填入大量用户,则搜索纯文本文件以在每个请求上对用户进行身份验证可能会非常慢。Apache还能够将用户信息存储在快速数据库文件中。mod_authn_dbm
模块提供AuthDBMUserFile
指令。可以使用dbmmanage
和htdbm
程序创建和操作这些文件。Apache模块数据库中的第三方模块提供了许多其他类型的身份验证选项。
最后,Require指令通过设置允许访问服务器的此区域的用户来提供进程的授权部分。
3. 允许多人进入
上面的指令只允许一个人(特别是用户名为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
组中列出并且密码文件中有条目的任何人都将被允许进入。
还有另一种方法可以让多个用户不那么具体。可以使用以下指令,而不是创建组文件:
Require valid-user
使用它而不是Require
用户rbowen
行将允许密码文件中列出的任何人以及正确输入密码的人。
4. 可能的问题
由于指定了基本身份验证的方式,因此每次从服务器请求文档时都必须验证用户名和密码。即使您正在重新加载同一页面以及页面上的每个图像(如果它们来自受保护的目录),这也是如此。可以想象,这会减慢一些事情。减慢速度的因素与密码文件的大小成正比,因为它必须打开该文件,然后沿用户列表向下,直到找到名字。每次加载页面时都必须这样做。
这样做的结果是,可以在一个密码文件中放入多少用户存在实际限制。此限制将根据您的特定服务器计算机的性能而有所不同,但是一旦超过几百个条目,速度可能会有一定下降,并且可能希望在此时考虑不同的身份验证方法。
5. 替代密码存储
由于在纯文本文件中存储密码存在上述问题,因此可能希望将密码存储在其他位置,例如数据库中。
mod_authn_dbm
和mod_authn_dbd
是使这成为可能的两个模块。可以选择dbm
或dbd
作为存储格式,而不是选择AuthBasicProvider
文件。
要选择dbm
文件而不是文本文件,例如:
<Directory "/www/docs/private">
AuthName "Private"
AuthType Basic
AuthBasicProvider dbm
AuthDBMUserFile "/www/passwords/passwd.dbm"
Require valid-user
</Directory>
6. 使用多个供应者
通过引入基于新提供程序的身份验证和授权体系结构,您不再需要锁定到单个身份验证或授权方法。实际上,可以混合和匹配任意数量的提供者,以便为您提供满足您需求的方案。在以下示例中,使用基于文件和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>
)允许应用逻辑,以便可以通过配置完全控制处理授权的顺序。
7. 超越授权
现在,可以应用授权的方式比仅针对单个数据存储的单个检查更灵活。现在可以使用顺序,逻辑和选择授权方式。
应用逻辑和排序
控制授权的应用方式和顺序过去一直是个谜。在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>