10.1 概述
您也许碰到过这样的情况,当您访问某个网站的时候,会收到403状态号,意思是禁止您查看请求的页面:
或者收到401状态号,表示对该页面的访问需要提供帐号、密码:
实现上述两个功能,就需要设置Apache的存取控制指令。
存取控制可以让网站管理员对某些资源的受众进行控制,比如给某些人看,不给某些人看,或者需要提供密码才能查看等等。
Apache的存取控制是通过对配置文件access.conf的修改完成的。对存取控制的实际操作是通过源文件http_access.c和http_auth.c来实现的。
下面我们来配置access.conf文件来达到上面提到的两个功能。
10.2 存取控制设置
在本节中我们通过配置Apache的access.conf文件来实现10.1节中提到的两个功能。其中第一小节讲解怎么设置这两种状态,第二小节对Apache所有有关存取控制的设置指令进行详细说明。
10.2.1 限制访问和认证访问
限制访问
简单的做法是让Apache拒绝所有的客户端访问。打开配置文件access.conf,找到<Limit GET>行,内容如下:
<Limit GET>
order allow,deny
allow from all
</Limit>
把其中的allow from all修改成deny from all。保存文件,重启Apache,通过浏览器访问您的站点首页,不出意外的话,您的浏览器应该会收到403状态号,即禁止访问。
禁止访问一般是禁止某些人的访问,在实际应用中,不会禁止所有人的访问,这样的站点是没有意义的,如果要禁止某些人的访问,可以参考10.2.2小节中的介绍。在这里我们仅仅重现10.1中实现的效果。
认证访问
首先还是修改access.conf文件中的<Limit GET>部分,修改后的内容类似于:
<Limit GET>
order allow,deny
allow from all
require valid-user
</Limit>
仅仅这样做是不够的。还需要创建认证文件和密码文件,认证文件中确定认证的方式、密码文件的位置、认证的提示语等内容;密码文件由Apache提供的工具创建,放在认证文件中指定的位置。
认证文件需要放在需要认证的目录下,一般以.htaccess做为文件名(这个名字可以通过配置文件设置)。我们在这里对整个站点认证,所以把认证文件放在站点根目录。相关信息如下所示:
[devel@RIZI htdocs]$ pwd
/home/devel/apache_0.6.5/htdocs
[devel@RIZI htdocs]$ tail .htaccess
AuthName "Private Level 9"
AuthType Basic
AuthUserFile /home/devel/apache_0.6.5/htdocs/.htpasswd
[devel@RIZI htdocs]$
.htpasswd文件即认证密码文件,如果您的电脑上安装了最近版本的Apache,可以通过新版本Apache提供的工具生成:
[devel@RIZI bin]$ pwd --我的新版Apache目录
/usr/local/apache/bin
[devel@RIZI bin]$ httpd –v --我的新版Apache版本
Server version: Apache/2.2.8 (Unix)
Server built: May 30 2008 15:51:42
[devel@RIZI bin]$ htpasswd -cb /home/devel/apache_0.6.5/htdocs/.htpasswd tsingien 123456
Adding password for user tsingien
[devel@RIZI bin]$
如果您没有较新版本的Apache,也没有关系,这个密码文件是一个文本文件,您可以手动创建。
该文件每行一条记录,每个记录格式是“用户名:加密密码”。我使用tsingien做为用户名,123456做为密码生成的密码文件内容为:
tsingien:SreeIymMXXp0U
设置好上面的步骤后,重启您的Apache,在浏览器里面输入您的站点地址,即可看到了10.1节中展示的登录对话框了。
组认证访问
除了针对某个用户的认证之外,还有针对组的认证。Apache 没有提供创建认证组文件的命令,它只是一个文本文件,用户可以使用任何的文本编辑器创建并修改此文件。该文件中每一行的格式如下:
组名:用户名 用户名 ……
在认证组文件中指定的用户名,必须先添加到认证口令文件中:
[devel@RIZI bin]$ pwd
/usr/local/apache/bin
[devel@RIZI bin]$ htpasswd -cb /home/devel/apache_0.6.5/htdocs/.htpasswd tsingien 123456
Adding password for user tsingien
[devel@RIZI bin]$ htpasswd -b /home/devel/apache_0.6.5/htdocs/.htpasswd laoli 123456
Adding password for user laoli
[devel@RIZI bin]$ tail /home/devel/apache_0.6.5/htdocs/.htpasswd
tsingien:SreeIymMXXp0U
laoli:YbHbUeJaxCkaE
[devel@RIZI bin]$
修改access.conf文件中的<Limit GET>部分为:
<Limit GET>
order allow,deny
allow from all
require group goodmen
</Limit>
创建/home/devel/apache_0.6.5/htdocs/.htgroup文件(组认证文件),内容为:
goodmen:tsingien laoli
badmen:xitele
修改文件/home/devel/apache_0.6.5/htdocs/.htaccess文件内容为:
AuthName "Private Level 9"
AuthType Basic
AuthUserFile /home/devel/apache_0.6.5/htdocs/.htpasswd
AuthGroupFile /home/devel/apache_0.6.5/htdocs/.htgroup
上面的设置说明,我们允许goodmen组里面的tsingien和laoli两个用户通过认证访问站点,不允许其它用户访问。
设置完成后,重新启动Apache,用浏览器访问站点,同样可以看到10.1节中展示的登陆对话框,使用tsingien或laoli帐号及其对应的密码即可登录。
下面,我们完整介绍一下Apache关于存取控制的设置指令。
10.2.2 设置指令详解
本章涉及到的指令包括AllowOverride、Option、AuthName、AuthType、AuthUserFile、AuthGroupFile以及Limit类指令。另外还包括列表目录类指令,列表目录类指令参考第九章的描述。
1. AllowOverride 指令
语法:AllowOverride All|None|
指令类型 [
指令类型 ] ...
功能:允许存在于.htaccess文件中的指令类型
示例:AllowOverride All
上例说明,
所有具有.htaccess上下文的指令都允许出现在.htaccess文件中。
AllowOverride指令可以有7个不同的值,名称和含义如下所示:
Limit:允许使用主机访问控制指令(Allow,Deny和Order)
Options:允许使用控制指定目录功能指令(Options)
FileInfo:允许使用控制文档类型指令(ErrorDocument等)
AuthConfig:允许使用鉴权指令(AuthName等)
Indexes:允许使用目录索引指令(AddIcon,HeaderName等)
None:.htaccess文件将被完全忽略
All:所有具有.htaccess 上下文的指令都允许出现在.htaccess文件中
2. Option 指令
语法:Options [+|-]可选项 [[+|-]可选项] ...
功能:配置在特定目录使用哪些特性。
示例:Options All
上例说明,将使用所有特性。
Options指令可以有8个不同的值,名称和含义如下:
Indexes:如果服务器收到了一个映射到该目录的URL请求,而目录下又没有DirectoryIndex(如index.html),那么服务器返回一个格式化目录列表。
Includes:允许服务器端包含。
IncludesNOEXEC:允许服务器端包含,但禁用#exec命令和#exec CGI。
FollowSymLinks:服务器会在此目录中使用符号连接。
SymLinksIfOwnerMatch:符号连接仅当与它的目的文件或目录具有相同的用户ID时才使用。简单理解就是符号链接的所有者和它指向的文件或目录是同一个人。
execCGI:允许执行CGI脚本。
None:都不允许。
All:所有特性。
3. AuthName 指令
语法:AuthName
auth-domain
功能:为目录的验证域设置名字
示例:AuthName "
九级权限"
上例说明,“九级权限”字符串将出现在浏览器要求验证的对话框中。
4. AuthType 指令
语法:AuthType Basic|Digest
功能:用户验证的类型
示例:AuthType Basic
上例说明,将使用Basic验证类型验证。
Digest
认证更安全,但是并非所有的浏览器都支持。0.6.5版本的Apache也不支持Digest类型的认证。
5. AuthUserFile 指令
语法:AuthUserFile
文件路径
功能:指定含有认证用户的用户名、密码列表的文件位置
示例: AuthUserFile /home/devel/apache-0.6.5/htdocs/.htpasswd
上例说明,含有认证用户的用户名、密码列表的文件是 /home/devel/apache-0.6.5/htdocs/.htpasswd 。
6. AuthGroupFile 指令
语法:AuthGroupFile
文件路径
功能:指定 包含用来执行用户认证的用户组列表文本文件
示例:AuthGroupFile
/home/devel/apache-0.6.5/htdocs/.htgroup
上例说明, 包含用来执行用户认证的用户组列表文本文件是/home/devel/apache-0.6.5/htdocs/. htgroup 。
7. <Limit> 指令
语法:<Limit
方法 [
方法 ] ... > ... </Limit>
功能:
限定访问控制仅施用于某些特定的HTTP方法
示例:<Limit GET>…</Limit>
上例说明,…部分的访问控制指令仅限于GET方法。
该类指令包括:order、allow、require、deny。下面我们一一加以说明:
7.1 order指令
语法:Order
ordering
功能: 控制缺省的访问状态和Allow与Deny指令被评估的顺序
示例:Order Deny,Allow
上例说明,Deny
指令在Allow
指令之前被评估。缺省允许所有访问。 任何不匹配Deny
指令或者匹配Allow
指令的客户都被允许访问服务器。
7.2 allow指令
语法:Allow from all|
host
功能:控制哪些主机能够访问服务器的一个区域
示例:Allow from 10.1.2.3
上例说明,允许IP为10.1.2.3的主机访问
7.3 require指令
语法:Require
entity-name [
entity-name ] ...
功能:
选择哪个认证用户能访问某个资源
示例:Require valid-user
上例说明,所有有效用户都可以访问这个资源。
Require
必须伴随AuthName
和AuthType
指令,以及诸如AuthUserFile
和AuthGroupFile
以确保其能够正确工作。
7.4 deny指令
语法:Deny from all|
host
功能:哪些主机被禁止访问服务器
示例:Deny from 10.2.3.4
上例说明,禁止IP为10.2.3.4的主机访问指定资源。
您可以通过修改配置文件来测试上面提到的7个指令及其子指令的效果,我们在下一节中通过Apache源代码来说明这些设置指令是怎么生效的。
10.3 代码注释
HTML1.0版本支持对资源的5种不同请求方法,它们分别是HEAD、GET、POST、PUT和DELETE。关于这5种请求方法的不同,可以参看11.1节的描述。
由于HEAD请求方法不需要服务器返回响应体,所以在存取控制的时候只处理其余的4种方法。
本章代码包括了http_access.c、http_auth.c和http_config.c中的一部分(parse_access_dir函数调用),由于http_config.c主要是读取配置信息的功能,所以针对它不在本章描述,请参考本书的第11章。
针对存取控制的结构体security_data在httpd.h定义:
typedef struct {
char *d; // 存取控制信息管理的路径
char opts; // Options的值
char override; // AllowOverride的值
int order[METHODS]; // 四种方法每种方法的order值
int num_allow[METHODS]; // 四种方法允许访问的主机个数
char *allow[METHODS][MAX_SECURITY]; // 四种方法允许访问的主机列表
int num_auth[METHODS]; // 四种方法可访问目录认证用户个数
char *auth[METHODS][MAX_SECURITY]; // 四种方法,可访问目录认证用户列表
char *auth_type; // 目录认证方式
char *auth_name; // 认证用户名
char *auth_pwfile; // 认证用户文件名
char *auth_grpfile; // 认证组文件名
int num_deny[METHODS]; // 四种方法,不允许访问的主机个数
char *deny[METHODS][MAX_SECURITY]; // 四种方法,不允许访问的主机列表
} security_data;
在实际应用的时候,使用一个数组来存储管理员对每个目录的设置信息:
security_data sec[MAX_SECURITY];
限于篇幅,注释代码部分请参看本书官网。
节选自《Apache源代码解析-基于Apache0.6.5》第十章。