PHP与MySQL权威指南
上QQ阅读APP看书,第一时间看更新

第一部分 准备篇

第1章 Apache基础

1.1 Apache介绍

随着网络技术的普及和不断发展,以及Web技术的不断完善,Web服务已经成为互联网上最重要的服务形式之一。原有的C/S模式正逐渐被B/S模式所取代。Apache是一种开源的HTTP服务器软件,可以在大多数主流的计算机操作系统中运行(包括UNIX、Linux及Windows),再加上其支持多平台且具有良好的安全性被广泛使用。

1.1.1 Apache工作原理

Web系统由客户端(浏览器)和服务器端两部分组成。Web系统架构也被称为B/S架构。最常见的Web服务器有Apache、IIS、Tomcat等,常用的浏览器有IE、Firefox、Maxthon等。当你想访问一个网页时,需要在浏览器的地址栏中输入该网页的URL(Uniform Resource Locator,简称为URL)地址,或者是通过超链接链接到该网页。浏览器会向该网页所在的服务器发送一个HTTP请求,服务器会对接收到的请求信息进行处理,然后将处理的结果返回给浏览器,最终将浏览器处理后的结果呈现给用户。

作为世界上最流行的Web服务器,Apache遵循的同样是HTTP协议,默认端口号为80,客户端和服务器端的通信步骤如下:

(1)客户端(浏览器)和Web服务器建立TCP连接,连接建立以后,向Web服务器发出访问请求(如get)。根据HTTP协议,该请求中包含了客户端的IP地址、浏览器的类型和请求的URL等一系列信息。

(2)服务器处理接收到的请求信息并将处理后的结果返回给客户端。

(3)客户端断开与服务器的连接。

1.1.2 Apache的特点

因为Apache是开源的,所以得到了开源社区的大力支持,吸引了众多优秀的开发人员参与其中,他们不断开发出各种新的功能特性,并对存在的缺陷进行修复。经过多年的不断完善,如今的Apache已经是最流行的Web服务器端软件之一。Apache的特点是简单、快速、高效和稳定。Apache服务器拥有以下特性:

❑支持最新的HTTP/1.1通信协议。Apache是最先使用HTTP/1.1协议的Web服务器之一,它完全兼容HTTP/1.1协议并与HTTP/1.0协议向后兼容。Apache已为新协议所提供的全部内容做好了必要的准备。

❑支持多计算机平台。Apache几乎可以在所有的计算机操作系统上运行,包括主流的UNIX、Linux及Windows操作系统。

❑配置文件简单,易操作。用户可以通过直接修改Apache的配置文件信息来修改Apache,操作起来十分方便。

❑支持实时监视服务器状态和定制服务器日志。Apache在记录日志和监视服务器自身运行状态方面提供了很大的灵活性,可以通过Web浏览器来监视服务器的状态,也可以根据自己的需要来定制日志。

❑支持多种方式的HTTP认证。

❑支持Web目录修改。用户可以使用特定的目录作为Web目录。

❑支持CGI脚本,如Perl、PHP等。

❑支持服务器端包含指令(SSI)。

❑支持安全Socket层(SSL)。

❑支持FastCGI。

❑支持虚拟主机。即通过在一台服务器上使用不同的主机名来提供多个HTTP服务。Apache支持基于IP、主机名和端口号三种类型的虚拟主机服务。

❑跟踪用户会话。当用户浏览基于Apache的Web站点时,可以通过Apache的mod_usertrack模块对其进行跟踪。

❑支持动态共享对象。Apache的模块可在运行时动态加载,这就意味着这些模块可以被装入服务器进程空间,从而减少系统的内存开销。

❑支持多进程。当负载增加时,服务器会快速生成子进程来处理,从而提高系统的响应能力。

❑支持第三方软件开发商提供的功能模块。比如Apache加载mod_jserv模块后可以支持Java Servlet,这样就可以运行Java应用程序了。

❑支持多线程和多进程混合模型的MPM。当MPM类型指定为worker时,由于是使用线程来处理,所以可以处理海量的请求,而系统资源的开销要小于基于进程的服务器。

1.2 Windows下Apache的部署

1.2.1 Windows下Apache的安装和配置

本节主要介绍在Windows操作系统中如何安装和配置Apache服务器。首先应该到Apache官方网站(http://httpd.apache.org/download.cgi)下载安装程序。当前的最新版本是2.3.5-alpha,这里我们以安装Apache2.2.15为例进行介绍。安装步骤如下:

(1)下载Apache的安装包httpd-2.2.15-win32-x86-no_ssl.msi,双击进入安装窗口,显示当前Apache的版本信息,如图1-1所示。

图1-1 Apache HTTP Server的安装界面

(2)点击“Next”按钮,进入Apache许可协议窗口,请仔细阅读协议内容,如果同意此协议,则选中“I accept the terms in the license agreement”单选按钮,如图1-2所示。

图1-2 Apache HTTP Server许可协议

(3)点击“Next”按钮,进入Apache HTTP服务器介绍窗口,如图1-3所示。这里主要介绍Apache是什么、最新的版本信息,以及配置文件更改等,建议不太了解的读者仔细阅读。

图1-3 Apache HTTP Server介绍

(4)点击“Next”按钮,进入服务器的相关信息设置页面,如图1-4所示。

图1-4 设置Apache HTTP Server信息

相关设置选项的解释如下:

❑Network Domain指已经或者将要注册的DNS域名。例如,如果你的DNS全称是www. shopnc.net,一般可以省略域名前的www,只输入shopnc.net部分。本地安装可以默认输入“localhost”字符串,或者127.0.0.1。

❑Server Name是服务器DNS域名的全称,例如www.phpchina.com。

❑Administrator’s Email Address是服务器管理员的邮箱,它会在默认的错误提示页面上显示给用户。

注意

这里所输入的信息只是对Apache的一些基本配置,可以在安装完成后通过编辑配置文件进一步配置。

❑“for All Users, on Port 80, as a Service - Recommended”为默认选项,Apache默认任何人都可以访问和监听端口号为80的服务器。

注意

如果机器中的80端口被占用(IIS和Resin的默认端口号都是80),在安装Apache之前需要先把它们的默认端口号改为非80,否则会因为端口号冲突而导致Apache无法正常启动。

❑ “only for the Current User, on Port 8080, when started Manually”只允许当前用户使用Apache,并且监听端口号为8080的服务器,使用时需要手动启动服务。

(5)点击“Next”按钮,选择安装类型,如图1-5所示。如果选择Typical(典型安装),则安装除开发模块需要的源码和库以外的所有内容;如果选择Custom(自定义安装),则可以自己选择要安装的内容。这里我们选择自定义安装。

图1-5 选择安装类型

(6)点击“Next”按钮,选择要安装的模块,如图1-6所示。点击文字前面的图标选择是否安装此模块,如果没有特殊要求,按默认设置安装即可。Apache的默认安装目录是C:\Program Files\Apache Software Foundation\Apache2.2\,点击“Change”按钮自定义安装目录。

图1-6 选择安装模块和自定义安装目录

(7)点击“Next”按钮,进入安装确认页面,如图1-7所示。如果想修改之前的信息,则可以点击“Back”按钮返回前面的步骤进行修改。

图1-7 安装确认页面

后面的步骤非常简单,按照提示进行操作即可完成安装。安装完成后我们可以测试一下Apache是否安装成功。首先看一下系统托盘中是否出现了监视Apache服务的图标,并且服务器是启动状态;然后打开浏览器,在地址栏输入“http://localhost/”或http://127.0.0.1,如果显示如图1-8所示的页面,说明Apache服务器已经安装成功了。

图1-8 Apache服务器安装成功

Apache服务器安装成功后,如果想对Apache进行配置,需要编辑安装目录下的conf子目录下的httpd.conf文件。该文件是Apache服务器的配置文件,编辑完成后一定要重新启动Apache服务器,这样才会生效。

上面详细地演示了Apache在Windows下安装和配置的完整过程,非常简单。Apache在Linux平台上的安装和配置的过程与此类似,限于篇幅,这里就不再重复演示。

1.2.2 启动、停止和重新启动Apache服务

在Windows操作系统中,Apache一般以服务的方式运行。在安装Apache时,如果你选择了“for all users”,Apache就会自动安装为一个服务。如果选择的是“only for the Current User”,可以在安装后手动将Apache注册为服务。注意,只有Administrators组的成员才能成功注册服务。

使用Apache Service Monitor工具可以查看和管理你所在网络上的所有机器上安装的Apache服务的状态,如图1-9所示。为了使用Apache Service Monitor管理Apache服务,首先必须自动或手动安装Apache服务。

图1-9 用Apache Service Monitor管理Apache服务的状态

可以在Apache安装目录的bin子目录下使用如下命令安装一个Apache服务。如果没有指定服务名称和配置文件,则在安装时使用默认服务名称Apache2.2,默认配置文件conf/httpd.conf。

        C:\Apache2.2\bin> httpd   -k   install

当在同一台机器上装有多个Apache服务时,必须为它们指定不同的名称,这样方便管理。可以使用下面的命令来指定服务的名称,其中“ApacheShop”为指定的服务名称。

        C:\Apache2.2\bin> httpd   -k   install   -n   ApacheShop

如果想为不同的服务指定不同的配置文件,可以在安装时使用如下的命令来指定:

        C:\Apache2.2\bin> httpd  -k  install  -n  ApacheShop -f "C:/Apache2.2/conf/my.conf"

如果想移除一个Apache服务,可以使用如下的命令,默认移除的是名为Apache2.2的服务。

        C:\Apache2.2\bin> httpd   -k   uninstall

也可以移除指定名称的服务,如下所示:

        C:\Apache2.2\bin> httpd   -k   uninstall   -n   ApacheShop

启动、停止和重新启动Apache服务的方法通常是使用Apache Service Monitor工具,另外也可以使用控制台命令:NET START Apache2.2和NET STOP Apache2.2,或者使用Windows控制面板下的服务。

在启动Apache服务之前,可以使用下面的命令来检查配置文件的正确性。

        C:\Apache2.2\bin> httpd   -n   Apache2.2   -t

还可以通过命令行控制Apache服务。启动一个已安装的服务:

        C:\Apache2.2\bin> httpd   -k   start

停止一个已安装的服务:

        C:\Apache2.2\bin> httpd   -k   stop

        C:\Apache2.2\bin> httpd   -k   shutdown

重新启动一个运行中的服务,可以使用下面的命令强制其重新加载配置文件:

        C:\Apache2.2\bin> httpd   -k   restart

httpd命令非常重要,详细介绍如下。

        httpd [-D name] [-d directory] [-f file]
              [-C "directive"] [-c "directive"]
              [-w] [-k start|restart|stop|shutdown]
              [-k install|config|uninstall] [-n service_name]
              [-v] [-V] [-h] [-l] [-L] [-t] [-S]

各参数选项的说明如下:

-D parameter 设置参数parameter,它配合配置文件中的<IfDefine>字段,用于在服务器启动和重新启动时有条件地跳过或处理某些命令。

-d serverroot 将ServerRoot指令的初始值设置为serverroot,它可以被配置文件中的ServerRoot指令覆盖。

-f config 在启动中使用config作为配置文件。如果config不以“/”开头,则它是相对于ServerRoot的路径,其默认值是conf/httpd.conf。

-k start|restart|graceful|stop|graceful-stop 发送信号使httpd启动、重新启动或停止。

-C directive 在读取配置文件之前,先处理directive的配置指令。

-c directive 在读取配置文件之后,再处理directive的配置指令。

-e level 在服务器启动时,设置LogLevel为level。用于在启动时,临时增加出错信息的详细程度,以帮助排错。

-E file 将服务器启动过程中的出错信息发送到文件file。

-R directory 当在服务器编译中使用SHARED_CORE规则时,它指定共享目标文件的目录为directory。

-h 输出一个可用的命令行选项的简要说明。

-l 输出一个静态编译在服务器中的模块的列表。它不会列出使用LoadModule指令动态加载的模块。

-L 输出一个指令的列表,其中包含了各指令的有效参数和使用区域。

-M 输出一个已经启用的模块列表,包括静态编译在服务器中的模块和作为DSO动态加载的模块。

-S 显示从配置文件中读取并解析的配置结果(目前仅显示虚拟主机的配置)。

-t 仅对配置文件执行语法检查。程序在语法解析检查结束后立即退出,或者返回“0”(OK),或者返回非0值(Error)。如果还指定了“-D DUMP_VHOSTS”,则会显示虚拟主机的详细配置信息。

-v 显示httpd的版本,然后退出。

-V 显示httpd和APR/APR-Util的版本和编译参数,然后退出。

-X 以调试模式运行httpd。仅启动一个工作进程,并且服务器不与控制台脱离。

下列参数仅用于Windows平台:

-k install|config|uninstall 安装Apache为一个Windows NT的服务;改变Apache服务的启动方式;删除Apache服务。

-n name 指定Apache服务的名称为name。

-w 保持控制台窗口的打开状态,使得可以阅读出错信息。

1.2.3 Apache支持PHP语言

我们先从PHP的官方网站http://php.net/downloads.php下载PHP的安装包(切记一定要下载编译过的安装包),这里我们以php-5.2.13-Win32版本为例进行讲解。

下载完成后解压安装包,把解压后的文件改名为“php5”并将其复制到C盘的根目录下,然后进入php5的目录,将文件php.ini-dist复制一份并改名为“php.ini”。在php.ini中需要修改以下几个地方:

❑设置扩展文件所在的目录:在文件中找到extension_dir = "./",将其更改为extension_dir = "C:/php5/ext/"。

❑开启常用的扩展。

■;extension=php_gd2.dll

■;extension=php_mbstring.dll

■;extension=php_mcrypt.dll

■;extension=php_mysql.dll

■;extension=php_mysqli.dll

在httpd.conf配置文件中,分号(;)表示注释该行内容。因此在需要开启某项扩展功能时,只要删除其前面的分号(;)即可。关于php.ini的详细介绍请参考本书的第二部分。接下来编辑Apache的配置文件httpd.conf,主要修改以下几个地方:

(1)加载用于处理PHP的模块。找到#LoadModule vhost_alias_module modules/mod_vhost_alias.so代码行,在下面添加以下代码:

        LoadModule php5_module "C:/php5/php5apache2_2.dll"   ##加载php处理模块

(2)在Apache中添加可识别PHP的MIME类型。找到AddType application/x-gzip .gz .tgz代码行,在下面添加以下代码:

        AddType application/x-httpd-php .php    ##php文件的MIME类型
        AddType application/x-httpd-source .phps    ##phps文件的MIME类型

(3)加载libmcrypt.dll和libmysql.dll类库文件。在httpd.conf文件后面添加如下的加载文件代码:

        LoadFile C:\php5\libmcrypt.dll   ##支持php_mcrypt.dll的类库
        LoadFile C:\php5\libmysql.dll    ##支持php_mysql.dll的类库

或者直接将C:\php5目录下的libmcrypt.dll和libmysql.dll复制到C:\WINDOWS\system32目录下。

(4)设置PHP的配置文件目录。在httpd.conf文件的最后添加下面的代码:

        PHPIniDir "C:/php5"   ##指定php.ini目录

也可以把修改好的php.ini文件复制到C:/WINDOWS/目录下。修改完成后保存文件,必须重启Apache服务,以重新加载配置文件。接下来测试一下我们的配置是否成功,进入Apache的Web根目录,新建一个名为“phpinfo.php”的文件,内容如下:

        <?php
        phpinfo();   //显示服务器的配置信息
        ?>

打开浏览器,在地址栏中输入http://localhost/phpinfo.php或http://127.0.0.1/phpinfo.php,如果出现如图1-10的界面,则说明PHP环境已经搭建好了。

图1-10 phpinfo()的显示界面

1.3 httpd.conf深入剖析

Apache服务器的配置文件位于C:\Program Files\Apache Software Foundation\Apache2.2\conf\目录下,一般会使用httpd.conf、access.conf和srm.conf三个配置文件来配置Apache服务器的行为。

httpd.conf提供了最基本的服务器配置,是对守护程序httpd如何运行的技术描述;srm.conf是服务器的资源映射文件,它告诉服务器各种文件的MIME类型,以及如何支持这些文件;access.conf用于配置服务器的访问权限,控制不同用户和计算机的访问限制;这三个配置文件控制着服务器各个方面的特性,因此为了服务器的正常运行需要设置好这三个文件。

实际上,目前常用的Apache版本已经将原来的httpd.conf、srm.conf与access.conf中的所有配置参数均放在了配置文件httpd.conf中,只是为了兼容老版本(使用这三个配置文件的方式来源于NCSA-httpd)才使用了三个配置文件,而所提供的access.conf和srm.conf文件中没有具体的配置。由于在新版本的Apache中,所有的设置都被放在了httpd.conf中,因此只需要调整这个文件中的配置即可。下面使用默认提供的httpd.conf为例,解释Apache服务器的各个配置选项。不必因为它提供的配置参数太多而烦恼,基本上这些参数都很直观,也可以在不加改动的情况下运行Apache服务器。但是,如果需要调整Apache服务器的性能,以及增加对某种特性的支持,就需要了解这些配置参数的含义。本节将对httpd.conf文件进行详细的讲解。

1.3.1 站点的基本配置

本节将重点介绍Apache对主站点进行配置的一些基本配置选项,如下所示。

❑ServerRoot "/mnt/software/apache2":Apache软件安装的位置。其他指定的目录如果没有指定绝对路径,则目录是相对路径。

❑PidFile logs/httpd.pid:第一个httpd进程(所有其他进程的父进程)的进程号文件位置。❑Listen 80:服务器监听的端口号。

❑ServerName www.clusting.com:80:主站点的名称(网站的主机名)。

❑ServerAdmin admin@clusting.com:管理员的邮件地址。

❑DocumentRoot "/mnt/web/clusting":主站点的网页存储位置。

❑DirectoryIndex index.html index.htm index.php:主页文件的设置(本例将主页文件设置为index.html、index.htm和index.php)。

1.3.2 服务器优化配置

Apache的主要优势就是能更好地支持多处理器,在编译时通过使用--with-mpm选项来决定Apache的工作模式。如果知道当前的Apache使用的工作机制,则可以通过httpd -l命令列出Apache的所有模块,从而就可以知道其工作方式。

(1)prefork。如果httpd -l列出了prefork.c,则需要对下面的这段参数进行配置:

        StartServers 5             #启动Apache时启动的httpd进程个数
        MinSpareServers 5          #服务器保持的最小空闲进程数
        MaxSpareServers 10         #服务器保持的最大空闲进程数
        MaxClients 150             #最大并发连接数
        MaxRequestsPerChild 1000#每个子进程被请求服务多少次后被kill掉。0表示不限制,推荐设置为1000

在该工作模式下,服务器启动后将启动5个httpd进程(如果加上父进程,一共6个,通过ps -ax|grephttpd命令可以看到)。当有用户请求连接时,Apache会使用一个空闲进程为该连接服务,同时父进程会fork一个子进程。直到内存中的空闲进程达到MaxSpareServers。该模式是为了兼容一些旧版本的程序。

(2)worker。如果httpd -l列出worker.c,则需要对下面的内容进行配置:

        StartServers 2             #启动Apache时启动的httpd进程个数MaxClients 150             #最大并发连接数MinSpareThreads 25         #服务器保持的最小空闲线程数MaxSpareThreads 75         #服务器保持的最大空闲线程数ThreadsPerChild 25         #每个子进程产生的线程数MaxRequestsPerChild 0      #每个子进程被请求服务多少次后被kill掉。0表示不限制,推荐设置为1000

该模式由线程来监听客户的连接。当有新客户连接时,由其中的一个空闲线程接受连接。服务器在启动后会启动两个进程,每个进程产生的线程数是固定的(由ThreadsPerChild决定),因此启动时有50个线程。当50个线程不够用时,服务器自动fork一个进程,再产生25个线程。

(3)perchild。如果httpd -l列出perchild.c,则需要对下面的内容进行配置:

        NumServers 5                         #服务器启动时启动的子进程数
        StartThreads 5                       #每个子进程启动时启动的线程数
        MinSpareThreads 5                    #内存中的最小空闲线程数
        MaxSpareThreads 10                   #内存中的最大空闲线程数
        MaxThreadsPerChild 2000              #每个线程最多被请求多少次后退出。0表示不受限制
        MaxRequestsPerChild 10000            #每个子进程服务多少次后被重新fork,0表示不受限制

该模式下,子进程的数量是固定的,线程数不受限制。当客户端连接到服务器时,由空闲的线程提供服务。如果空闲的线程数不够,子进程就会自动产生线程来为新的连接服务。该模式用于多站点服务器。

1.3.3 HTTP响应头的信息配置

默认情况下,Apache安装时会显示版本号及操作系统的版本,甚至会显示服务器上安装了哪些Apache模块。这些信息可能会被黑客利用,并且黑客还可以从中得知你所配置的服务器上的很多设置都是默认状态。我们可以通过修改ServerTokens模块对所显示的内容进行设置。

ServerTokens用来设置http头部返回的Apache版本信息。一般会带有如下几个参数,这些参数的含义和作用说明如下。

❑Prod:仅软件名称,例如apache。

❑Major:包括主版本号,例如apache/2。

❑Minor:包括次版本号,例如apache/2.0。

❑Min:仅Apache的完整版本号,例如apache/2.0.54。

❑OS:包括操作系统类型,例如apache/2.0.54(Unix)。

❑Full:包括Apache支持的模块及模块版本号,例如Apache/2.0.54 (Unix) mod_ssl/2.0.54 OpenSSL/0.9.7g。

1.3.4 持久性连接配置

在Apache的httpd.conf中,KeepAlive表示保持连接活跃,类似于MySQL的永久连接。换句话说,如果将KeepAlive设置为On,那么来自同一客户端的请求就不需要再连接一次,避免每次请求都要新建一个连接而加重服务器的负担。

KeepAlive的连接活跃时间当然是受KeepAliveTimeOut限制的。如果第二次请求和第一次请求之间超过了KeepAliveTimeOut的时间,第一次连接就会中断,再新建第二个连接。所以,一般情况下,图片较多的网站应该把KeepAlive设为On。但是KeepAliveTimeOut应该设置为多少秒就是一个值得讨论的问题了。如果KeepAliveTimeOut设置的时间过短,例如设置为1秒,那么Apache就会频繁地建立新连接,当然会耗费不少的资源;反过来,如果KeepAliveTimeOut设置的时间过长,例如设置为300秒,那么Apache中肯定有很多无用的连接会占用服务器的资源,也不是一件好事。所以,到底要把KeepAliveTimeOut设置为多少,则要根据网站的流量和服务器的配置而定。相关配置说明如下:

❑KeepAlive On:开启持久性连接功能。即当客户端连接到服务器时,下载完数据后仍然保持连接状态。

❑MaxKeepAliveRequests 100:一个连接服务的最多请求次数。

❑KeepAliveTimeout 30:测试一次连接中的多次请求传输之间的时间,如果服务器已经完成了一次请求,但一直没有接收到客户程序的下一次请求,在间隔超过了这个参数设置的值之后,服务器就断开连接。默认值是15秒。

1.4 日志记录

要有效地管理Web服务器,反馈服务器的活动、性能及出现的问题就很有必要。Apache HTTP服务器提供了非常全面而灵活的日志记录功能。

1.4.1 日志的配置

Apache为管理员提供了很全面的日志管理工具来对服务器的活动进行事后分析。Apache提供了多种不同的记录日志,但是对安全专业人士来说最重要的是访问日志。这个灵活的工具还具有相当多的自定义功能,可以按照你的需要很方便地记录尽可能多或少的日志,以保证有效的分析。

(1)ErrorLog file-path|syslog[:facility]

指定了当服务器遇到错误时记录错误日志的文件。如果file-path不是一个以斜杠(/)开头的绝对路径,那么它会被认为是一个相对于ServerRoot的相对路径。我们来看下面的示例:

        ErrorLog "logs/error.log"
        LogFormat format|nickname [nickname]

本指令的功能是定义访问日志的记录格式。例如:

        LogFormat "%h %l %u %t \"%r\" %>s %b" common

日志记录中还包含将被原样写入日志的文本字符串及C风格的控制字符“\n”和“\t”,以实现换行与制表。文本中的引号和反斜杠应通过“\”来转义。日志文件的具体格式如表1-1所示。

表1-1 日志文件的格式

(2)LogLevel

LogLevel用于调整记录在错误日志中的信息的详细程度。可以选择表1-2所示的level,依照重要性降序排列。

表1-2 Level重要性等级列表

(3)CustomLog file|pipe format|nickname [env=[!]environment-variable]

CustomLog指令用来对服务器的请求进行日志记录。可以指定日志的格式,也可以使用环境变量根据请求的特征来自由地组织日志。

1.4.2 错误日志

错误日志是最重要的日志文件,其存放位置取决于ErrorLog指令。如果服务器在启动时或在运行中有问题,首先就应该查看错误日志。错误日志通常被写入error.log文件中。错误日志的格式相对灵活,并且可以附加文字来描述。例如:

          [Fri Mar 12 23:04:192010] [error] [client 127.0.0.1] script 'E:/www/test.php'
    not found or unable to stat

各个参数的说明如下:

❑[Fri Mar 12 23:04:192010]:错误发生的日期和时间。

❑[error]:错误的级别,只有高于LogLevel指令指定级别的错误才会被记录。

❑[client 127.0.0.1]:是导致错误的IP地址。

❑script 'E:/www/test.php' not found or unable to stat:错误的原因。

此例中,客户访问了一个不存在的文件,导致服务器产生了一个错误。服务器在记录被访问的文件时,用的是文件系统路径,而不是Web路径。

用户可以增加或删除错误日志的项,但是对于某些特殊请求,在访问日志(access log)中也会有相应的记录。例如,上述例子在访问日志中也会有相应的记录,其状态码是404。因为访问日志也可以定制,所以可以从访问日志中得到错误事件的更多信息。

1.4.3 访问日志

访问日志会记录对Web服务器的所有请求,其存放文件和记录的格式取决于CustomLog指令,LogFormat指令可以定义日志的内容格式。对于日志管理,首先必须产生访问日志,然后才能分析日志,从而得到有用的统计信息。下面介绍如何配置服务器的访问日志。

访问日志的记录格式非常灵活,使用风格很像C语言中的printf()函数的格式。可以通过下面介绍的几种日志格式查看用于mod_log_config模块的格式字符串。

(1)通用日志格式(Common Log Format)

          LogFormat "%h %l %u %t \"%r\" %>s %b" common
          CustomLog "logs/access.log" common

各参数的说明如下:

1)LogFormat定义了一种特定的记录格式的字符串,并给它取了个别名叫common,其中的“%”表示服务器用某种信息替换,其他字符则不作替换。引号(")必须加反斜杠转义,以避免被解释为字符串的结束符。格式字符串还可以包含特殊的控制符,如换行符"\n"和制表符"\t"。

2)CustomLog定义了一个使用指定别名的日志文件,除非其文件名是以斜杠开头的绝对路径,否则其路径就是相对于ServerRoot的相对路径。

通用日志格式(CLF)的记录格式被许多不同的Web服务器所采用,并被许多日志分析工具所识别,它产生的记录字符串如下所示:

          127.0.0.1- - [12/Mar/2010:23:04:19 +0800] "GET /test.php HTTP/1.1" 404206

各参数的说明如下:

1)127.0.0.1:发送请求到服务器的客户端IP地址。如果HostnameLookups设为On,则服务器会尝试解析这个IP地址的主机名并替换此处的IP地址,但是不推荐这样做,因为它会明显地拖慢服务器,最好是用一个日志后续处理程序来判断主机名,比如logresolve(logresolve是一个解析Apache访问日志中IP地址的后处理程序,为了使对名称服务器的影响降到最低,它拥有极为自主的内部散列表缓存,使每个IP值仅仅在第一次从日志文件中读出时才被解析一次)。如果客户端和服务器之间存在代理,那么记录中的这个IP地址就是那个代理的IP地址,而不是客户端的真实IP地址。

2)第一个"-":由客户端identd进程判断的RFC1413身份(identity),输出中的符号"-"表示此处的信息无效。此信息通常很不可靠,不应该被使用,除非在严格控制的内部网络中。只有将IdentityCheck指令设为On,Apache才会试图获取这项信息。

3)第二个"-":HTTP认证系统得到的访问该网页的客户端标识(userid),环境变量REMOTE_USER会被设为该值并提供给CGI脚本。如果状态码是401,则表示客户端未通过认证,此值没有意义。如果网页没有设置密码保护,则此项将是"-"。

4)[12/Mar/2010:23:04:19 +0800]:服务器完成请求处理时的时间,其格式是[日/月/年:时:分:秒 时区]。可以在格式字符串中使用 %{format}t来改变时间的输出形式,其中的format与C语言标准库中的strftime()用法相同。

5)"GET /test.php HTTP/1.1":客户端发出的包含许多有用信息的请求行。可以看出,该客户端的动作是GET,请求的资源是/test.php,使用的协议是HTTP/1.1。另外,还可以记录其他信息,如格式字符串"%m %U%q %H"会记录动作、路径、查询字符串及协议等。

6)404:服务器返回给客户端的状态码。该信息非常有价值,因为它指示了请求的结果:成功响应(以2开头),被重定向(以3开头)、出错(以4开头),或产生了服务器端错误(以5开头)。

7)206:返回给客户端的不包括响应头的字节数。如果没有信息返回,则此项应该是"-",如果希望记录为"0"的形式,则应该用%B。

(2)组合日志格式(Combined Log Format)

另一种常用的记录格式是组合日志格式,形式如下:

        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
        CustomLog "logs/access.log" combined

这种格式与通用日志格式类似,但是多了两个 %{header}i项,其中的header可以是任何请求头。这种格式的记录如下:

        127.0.0.1- - [13/Mar/2010:00:38:38 +0800] "GET /test.php HTTP/1.1" 404206 "-"
        "Mozilla/4.0   (compatible;   MSIE   7.0;   Windows   NT   6.1;   Trident/4.0;
    QQPinyinSetup  620;  SLCC2;  .NET  CLR  2.0.50727;  .NET  CLR  3.5.30729;  .NET  CLR
    3.0.30729; Media Center PC 6.0; InfoPath.2)"

其中,多出来的项是"-",它是"Referer"请求头。此项指明了该请求是从哪个网页提交过来的,如果内容为空,则此项显示"-"。"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1;Trident/4.0; QQPinyinSetup 620; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2)"是"User-Agent"请求头,此项是客户端提供的浏览器识别信息。

1.5 虚拟主机

所谓虚拟主机是指在一台机器上虚拟出多台Web服务器。举个简单的例子,一家公司有多个不同域名的网站,它只需要购买一台物理服务器,通过配置虚拟主机实现为多个站点提供Web服务,而访问者通过输入不同的域名来获取想要的Web信息。

在Apache的配置文件中,通过<VirtualHost>区块指令来识别不同的身份,也就是我们通常说的虚拟主机。Apache设置虚拟主机一般采用两种方案:基于主机名的虚拟主机和基于IP地址的虚拟主机。这两种方案可以单独来使用,也可以混合使用,你可以根据实际工作需要来选择一种适合自己的方案。

1.5.1 基于主机名的虚拟主机

要想在只有一个IP地址的服务器上支持多个网站,我们可以通过设置虚拟主机的主机名来进行区分。这样就可以达到多个虚拟主机共享同一个IP地址的目的,同时也可以缓解IP地址不足的压力。

基于主机名的虚拟主机的配置相对比较简单,因为只需要配置DNS服务器,将每个主机名映射到正确的IP地址,然后配置Apache服务器,使其能辨识不同的主机名即可。

注意

在Apache服务器配置中创建一个虚拟主机并不会自动在你的DNS中对主机名进行相应的更新,你必须自己在DNS中添加域名来指向你的IP地址。否则,你的Web站点将无法访问。你可以在本地的hosts文件中添加shop.example.com、bbs.example. com和myshop.example.com三个域名来进行测试,但这种方法仅适用于有这些hosts文件的主机。

现在可以通过域名shop.example.com来访问你的主机,但如果你想在同一IP地址上添加一个新的虚拟主机,用域名bbs.example.com来访问,那么需要在httpd.conf文件中加入以下代码:

        NameVirtualHost *:80
        <VirtualHost *:80>
        ServerName shop.example.com
        ServerAlias myshop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #这里可以添加其他指令
        </VirtualHost>
        <VirtualHost *:80>
        ServerName bbs.example.com
        DocumentRoot C:/Apache2.2/htdocs/bbs
        #这里可以添加其他指令
        </VirtualHost>

因为星号匹配所有的IP地址,所以主服务器不接收任何请求。上例中shop.example.com首先出现在配置文件中,所以它拥有最高的优先级,可以认为是默认服务器或主服务器。这意味着,如果一个请求不能与某个ServerName指令相匹配,它将会由第一个<VirtualHost>区块来提供服务。

NameVirtualHost指定了主机的IP地址和端口号(默认80端口可省略),如果想让主机可以在所有地址上运行,可以使用"*"作为NameVirtualHost的参数。每个<VirtualHost>区块对应的是一个虚拟主机的配置。<VirtualHost>的参数与NameVirtualHost的参数必须是一致的。在每个<VirtualHost>区块中,只要包含一个指定服务主机的名称的ServerName指令和一个指向主机内容所在文件系统目录的DocumentRoot指令即可。

由于一些特殊需要,很多服务器希望能通过多个域名来访问。我们可以通过ServerAlias指令来指定多个域名,多个域名之间使用空格来区分,例如:

        ServerAlias myshop.example.com othershop.example.com

也可以建立一个默认虚拟主机来接受所有客户端请求,并对主机进行一些错误处理,例如找不到主机。

        NameVirtualHost *
        <VirtualHost *>
        ServerName default
        DocumentRoot C:/Apache2.2/htdocs/shop
        ErrorDocument 404 C:/Apache2.2/htdocs/shop/error.html
        </VirtualHost>

当然,也可以用一个固定的IP地址来代替NameVirtualHost和<VirtualHost>指令中的"*",以达到一些特定的目的。然而,当IP地址无法确定时,使用"*"是很方便的,例如,你的ISP给你配置的是动态IP地址,而你又使用了某种动态域名解析系统。因为"*"匹配任何IP地址,所以在这种情况下,无论IP地址如何变化,你都不需要另外进行配置。

1.5.2 基于IP地址的虚拟主机

在一个拥有多个IP地址的服务器上,如果想要通过多个IP地址请求来提供相同的内容,可以配置基于每个IP地址的虚拟主机来达到这个目的。服务器中基于IP地址的各个虚拟主机必须拥有不同的IP地址。

例如,在同一台服务器上使用两个IP地址(192.168.0.2和192.168.0.3分别对应shop. example.com和myshop.example.com)请求来获取相同内容,我们以此为例来介绍基于IP地址的虚拟主机配置。在httpd.conf中加入以下代码:

        NameVirtualHost 192.168.0.2
        NameVirtualHost 192.168.0.3
        <VirtualHost 192.168.0.2>
        ServerName shop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #这里可以添加其他指令
        </VirtualHost>
        <VirtualHost 192.168.0.3>
        ServerName myshop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #这里可以添加其他指令
        </VirtualHost>

如果存在主服务器,那么所有没有出现在任何一个<VirtualHost>区块中的请求(例如对localhost的请求)都会由主服务器来提供服务。

1.6 URL重写

随着Web技术的发展,URL的展现形式也越来越多样化,比如说现在比较流行网页静态化,这样一方面可以加快访问速度,另外一方面也可以更好地被搜索引擎录入。并不是你看到的所有静态网页都是通过静态化生成的,这可能只是一种欺骗手段,可能是运用了另一种更高效的缓存技术。可以通过URL重写来达到欺骗的目的,Apache提供了一个mod_rewrite模块来实现URL的重写功能。

1.6.1 mod_rewrite模块

mod_rewrite模块提供了一种灵活而且强大的URL操作机制,可以使服务器操作整个URL。它基于正则表达式分析器的重写引擎来实时重写URL请求。mod_rewrite模块中的指令分为服务器级和目录级,前者的作用域是该服务下的所有网站,指令在httpd.conf中配置;后者只对.htaccess文件所在的目录有效,并在.htaccess中进行配置。重写操作包括内部子处理、内部代理处理和外部请求转向。其主要的工作步骤如下:

(1)接受一个具有一定规则的URL请求

(2)按照设定的规则进行匹配,匹配成功则会生成匹配结果。

(3)通过匹配结果进行下一步操作。

mod_rewrite模块默认是不开启的,需要先开启它。方法是先打开httpd.conf,找到#LoadModule rewrite_module modules/mod_rewrite.so,去掉前面的注释,然后保存即可。

下面我们来实践一个简单的例子,首先在DocumentRoot目录下新建一个名为shop的文件夹,然后在该目录下创建两个文件,文件内容分别如下所示。

❑旧文件

        old.html
        <html>
        <head>URL重写测试</head>
        <body>
        我是旧的文件
        </body>
        </html>

❑新文件

        new.html
        <html>
        <head>URL重写测试</head>
        <body>
        我是新的文件
        </body>
        </html>

通过浏览器访问http://localhost/shop/old.html和http://localhost/shop/new.html显示的结果都是正常的,接下来我们对old.html的URL进行重写,在shop目录下创建名为.htaccess的文件,内容如下:

        #开启重写引擎
        RewriteEngine On
        #重写URL规则
        RewriteRule    ^old\.html$   new.html

我们再次访问http://localhost/shop/old.html时,页面显示的不是old.html的内容,而是new.html的内容。

1.6.2 常用指令

在实际工作中为了提高工作效率,也可以通过Apache提供的一些指令来实现所需的各种功能,下面就一些常用指令进行详细讲解。

1. RewriteEngine指令

RewriteEngine指令用来开启或关闭URL重写引擎。如果设置为Off,Apache在运行时则不执行URL重写操作。RewriteEngine指令语法如下:

        RewriteEngine On|Off

注意 如果虚拟主机中需要URL的重写功能,则必须设置RewriteEngine On指令。

2. RewriteBase指令

RewriteBase指令用来设置URL重写的根目录。如果不设置该指令,则默认是.htaccess文件所在的目录。RewriteBase指令语法如下:

          RewriteBase URL-path

例如,要想通过访问旧的URL地址(http://localhost/shop/old.html)来显示新的URL地址(http://localhost/shop/new.html)下的页面内容,则需要在shop目录下的.htaccess文件(如果.htaccess文件不存在,则需要手动创建)中设置下面的指令:

          # /shop/.htaccess -- /shop目录的配置文件
          #开启重写引擎
          RewriteEngine On
          # URL重写目录,“/”为当前目录
          RewriteBase   /
          # 重写规则
          RewriteRule    ^old\.html$   new.html

注意

保存后需要重启Apache服务器。shop目录下必须存在new.html文件,否则会提示404错误。

3. RewriteCond指令

RewriteCond指令定义了一个重写规则条件。在一个RewriteRule指令之前可以有一个或多个RewriteCond指令。重写规则仅在当前URI与Pattern匹配并且满足此条件时才会起作用。RewriteCond指令的语法如下:

          RewriteCond TestString CondPattern [flags]

TestString是一个纯文本的字符串,还可以包含下列的可扩展部分:

(1)RewriteRule反向引用

引用形式:$N(0 <= N <= 9)。引用当前(带有若干RewriteRule指令的)RewriteCond中与Pattern匹配的分组成分。

(2)RewriteCond反向引用

引用形式:%N(1 <= N <= 9)。为当前RewriteCond条件中最后一个与pattern匹配的分组部分提供访问的引用形式。

(3)服务器变量

引用形式:%{ NAME_OF_VARIABLE }。NAME_OF_VARIABLE可以是表1-3中的任意一个字符串。

表1-3 NAME_OF_VARIABLE指定字符串列表

这些变量都对应于类似命名的HTTP MIME头,Apache服务器的C变量或Unix系统中的struct tm字段,其中大多数变量在其他手册或CGI规范中都有说明。还需要注意以下几点:

1)变量SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的,即Apache服务器内部的request_rec结构中的filename字段的值。第一个变量也称为CGI变量名,而第二个变量恰好对应的是REQUEST_URI(包含request_rec中uri字段的值)。

2)%{ENV:variable}中的variable可以是任意环境变量,可通过查找Apache内部结构或通过函数getenv()从Apache服务器进程中来获得。

3)%{SSL:variable} 中的variable可以是一个SSL环境变量的名字,无论是否加载mod_ssl模块都可以使用,如果没有加载,则为空字符串,比如%{SSL:SSL_CIPHER_USEKEYSIZE}将会演变为128。

4)%{HTTP:header}中的header可以是任意HTTP MIME头的名称,可以通过发送一个HTTP请求来获得,比如%{HTTP:Proxy-Connection}是HTTP header Proxy-Connection的值。

5)%{LA-U:variable}可用于查找在执行一个内部(基于URL的)子请求后确定的最终值。可以用于重写一个目前未知但是会在之后的过程中设置的变量。例如,需要在服务器级的配置(httpd.conf文件)中根据REMOTE_USER变量进行重写,就必须使用%{LA-U:REMOTE_USER},因为此变量是在URL重写(mod_rewrite)操作之后的授权阶段设置的。另一方面,因为mod_rewrite是在API命名修正阶段实现对目录级(.htaccess文件)的配置的,而授权阶段优先于此阶段,所以在这种情况下使用%{REMOTE_USER}。

6)%{LA-F:variable}用于在执行一个内部(基于文件名的)子请求后确定变量的最终值。在大多数情况下,与上述的LA-U是相同的。

7)CondPattern是一个条件模板,即一个与TestString进行匹配的正则表达式。它是一个与Perl兼容的正则表达式,它有如下两个特点:

❑可以给模式字符串加一个"!"前缀,指定一个非匹配模式。

❑有一些特殊的CondPatterns变种,它们并不是真正的正则表达式字符串,主要有如下形式:

■'<CondPattern':小于字符串CondPattern。将CondPattern作为一个普通的字符串并与TestString根据字典顺序进行比较,如果TestString小于CondPattern,则为真。

■'>CondPattern':大于字符串CondPattern。将CondPattern作为一个普通的字符串与TestString按字典顺序进行比较,如果TestString大于CondPattern,则为真。

■'=CondPattern':等于字符串CondPattern。将CondPattern作为一个普通的字符串与TestString按字典顺序进行比较,如果TestString等于CondPattern(两个字符串完全相等),则为真。

■'-d':判断是否是目录。把TestString作为一个路径名并测试它是否为一个已存在的目录。

■'-f':判断是否为文件。把TestString作为一个路径名并测试它是否为一个已存在的文件。

■'-s':判断是否为非空的文件。把TestString作为一个路径名并测试它是否为一个已存在的且大小大于0的文件。

■'-l':判断是否为符号链接。把TestString作为一个路径名并测试它是否为一个已存在的符号连接。

■'-x':判断是否为有可执行权限的文件。把TestString作为一个路径名并测试它是否为一个已存在的并且具有可执行权限的文件。该权限由操作系统检测。

■'-F':判断是否是通过子请求访问存在的文件。检查TestString是否为一个有效的文件,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用!

■'-U':判断是否是通过子请求访问存在的URL。检查TestString是否为一个有效的URL,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用!

注意 这些测试都可以用惊叹号作前缀('!')来实现相反条件的测试。

另外,RewriteCond指令的后面可选择添加flags标记,多个标记之间以逗号分隔。目前只有2个标记,分别是:NC(不区分大小写)和OR(与下一个条件建立或的关系)。当RewriteCond指令的判断条件为真时,它下面的RewriteRule指令才会被执行。例如,根据客户端使用的浏览器的不同来显示不同的页面,设置内容如下:

        #开启重写引擎
        RewriteEngine on
        #如果是火狐浏览器,则显示homepage.max.html
        RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
        RewriteRule ^/$ /homepage.max.html [L]
        #如果是IE浏览器,则显示homepage.min.html
        RewriteCond %{HTTP_USER_AGENT} ^MSIE.*
        RewriteRule ^/$ /homepage.min.html [L]
        #不满足上面两种条件,则显示homepage.std.html
        RewriteRule ^/$ /homepage.std.html [L]

4. RewriteRule指令

RewriteRule指令用于为重写引擎定义重写规则。我们可以同时配置多个RewriteRule指令,但是一定要注意它们的先后顺序。RewriteRule指令的语法如下:

        RewriteRule Pattern Substitution [flags]

Pattern用于重写当前URL的正则表达式,Substitution是与Pattern匹配成功后用来替换的字符串。除了纯文本外,还可以包含:

(1)对Pattern的反向引用($N)。

(2)对最后匹配的RewriteCount的反向引用(%N)。

(3)规则条件测试字符差(%{VARNAME})中的服务器变量。

flags(可选)用于重写规则标记,多个标记之间用半角逗号(,)分隔。重写规则标记的相关参数如下所示。

(1)C:用于关联下一条规则。如果当前规则匹配成功,则该标记不起作用,否则与之关联的规则都会被跳过而不进行匹配。

(2)CO=NAME:VAL:domain[:lifetime[:path]]':用户在客户端设置一个cookie。NAME是cookie的名称,VAL是cookie的值。domain是cookie的域,lifetime(可选)是cookie的有效期(分钟),path(可选)是cookie的路径。

(3)E=VAR:VAL:用于设置环境变量。VAR是变量名,VAL是变量的值。

(4)F:用于强制禁止当前URL。反馈一个HTTP响应码403(被禁止的)。

(5)G:用于强制放弃当前URL。反馈一个HTTP响应码410(已放弃的)。

(6)H:用于强制指定目标文件的内容处理器为Content-handler。

(7)L:用于停止重写操作,并且不再应用其他的重写规则。

(8)N:用于重新执行重写操作。

(9)NC:使Pattern忽略大小写。在Pattern与当前URL匹配时,'A-Z'和'a-z'没有区别。

(10)NE:用于阻止mod_rewrite对重写结果应用常规的URI转义规则。一般情况下,特殊字符('%','$',';'等)会被转义为等值的十六进制编码('%25', '%24', '%3B'等),使用此标记可以阻止这些符号的转义。

(11)NS:用于跳过对内部子请求的重写规则。

(12)P:用于substitution部分在内部作为代理请求被强制发送,并中断重写处理,然后交给mod_proxy模块(mod_proxy模块必须是已启用状态)。

(13)PT:强制重写引擎将request_rec内部结构中的uri字段设置为filename字段的值,使得RewriteRule指令的输出内容(从不同的URI转换到filename的)能够被Alias、ScriptAlias、Redirect等指令进行后续处理。

(14)QSA:强制重写引擎在已有的substitution字符串中追加一个查询字符串,而不是替换它。

(15)R:如果Substitution的前缀是以http://thishost[:thisport]/开头的,则强制执行外部重定向。如果没有指定code,则产生一个HTTP响应码302(临时性移动的)。如果想使用300~400范围内的其他响应码,在此指定即可。

(16)S=num:强制重写引擎跳过当前规则之后的num个规则。

(17)T=MIME-type:强制目标文件的MIME类型。

5. RewriteLog指令

RewriteLog指令设置用于记录所有重写操作的日志文件的名称。如果此文件名不以斜杠(/)开头,则它是相对于Server Root的,此指令应该在每个服务器级别的配置中仅出现一次。RewriteLog指令的语法如下:

          RewriteLog file-path

注意

如果要关闭对重写操作的记录,可以删除或注释掉RewriteLog指令,或者设置RewriteLogLevel的值为0。

6. RewriteLogLevel指令

RewriteLogLevel指令设置重写引擎日志的详细程度的级别。默认为0,意味着不记录;9或更大的值则意味着记录所有操作。RewriteLogLevel指令的语法如下:

          RewriteLogLevel Level

注意

较高的Level值会使Apache服务器的速度急剧下降!大于2的Level值只用于调试目的!

1.7 实战案例

1.7.1 防止图片盗链

所谓盗链是指服务提供商自己不提供服务的内容,而是通过技术手段直接在自己的网站上向最终用户提供其他服务提供商的服务内容,以骗取用户的浏览和点击率。受益者不提供资源或提供很少的资源,而真正的服务提供商却得不到任何的收益。像图片、视频等这些比较大的文件都有可能成为被盗的对象。一旦文件被盗,就会增加服务器的流量,影响网站的访问速度。虽然我们不能100%的保护这些文件不被别人盗用,但可以通过HTTP Referer进行限制。使用Apache可以很方便地进行设置。假设主机域名为www.example.com,在文件.htaccess中的配置如下:

        RewriteEngine on
        RewriteCond %{HTTP_REFERER} !^$ [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.example.com [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.google.cn [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.baidu.com [NC]
        RewriteRule .*\.(gif|jpg)$ http://www.example.com/default.jpg [R,NC,L]

该配置的说明如下:

❑RewriteCond %{HTTP_REFERER} !^$ [NC]

允许HTTP_REFERER为空时访问,即允许用户在浏览器地址栏中直接输入图片地址时显示图片。一般来说这个选项是可选的,建议这样设置。如果将HTTP_REFERER强制限制不能为空,那么当用户通过代理服务器访问时,可能会导致一些问题。

❑RewriteCond %{HTTP_REFERER} !www.example.com [NC]

设置允许访问的HTTP_REFERER来源,包括自身站点,以及Baidu、Google、Yahoo!等。

❑RewriteRule .*\.(gif|jpg)$ http://www.example.com/default.jpg [R,NC,L]

设置图片被盗链时用于替换的图片,如果有图片被盗链,显示的是default.jpg。注意,默认图片所在的路径最好跟配置文件不在同一目录下,图片越小越好。如果不想设置替换图片,可以使用下面的语句:

        RewriteRule .*\.(gif|jpg)$ - [F]

❑NC、R、L、F标记解释

■NC:不区分大小写。

■R:强制重定向。

■L:立即停止重写操作。

■F:强制禁止URL。

1.7.2 Apache伪静态

页面静态化是现在比较流行的一种页面处理技术,静态页面既能提高访问速度,也能被搜索引擎更好地抓取。比较常用的方式有两种:一种是通过程序来生成静态化页面,另一种是通过Apache的rewrite模块来实现,这里我们以Windows下的Discuz7.2为例进行介绍。Discuz 7.2的安装见本书的第22章。

首先,进入Discuz后台,依次打开“全局”→“优化设置”→“搜索引擎优化”菜单选项,如图1-11所示。

图1-11 Discuz7.2后台的全局优化设置

在“URL静态化”区块中,选中需要静态化的页面,点击下方的“提交”按钮即可。这时直接通过静态页面来访问会报错,我们还需要在Apache的配置文件中进行相关的设置。

打开httpd.conf,找到#LoadModule rewrite_module modules/mod_rewrite.so并去掉前面的注释(#),然后在文件的最后添加以下代码:

        <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^(.*)/archiver/((fid|tid)-[\w\-]+\.html)$ $1/archiver/index.php?$2
        RewriteRule
        ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.php?fid=$2&page=$3
        RewriteRule
        ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/viewthread.php?tid= $2&extra=page\%3D$4&page=$3
        RewriteRule ^(.*)/space-(username|uid)-(.+)\.html$ $1/space.php?$2=$3
        RewriteRule ^(.*)/tag-(.+)\.html$ $1/tag.php?name=$2
        </IfModule>
        保存修改好的文件,重启Apache服务就可以了。

1.7.3 用户访问权限设置

在维护网站时,为了安全起见,一些重要的目录是不允许普通用户访问的,我们可以给这些目录设置一个指定用户才能访问的权限。Apache的mod_auth_basic模块就提供了相关的功能,我们以Windows下的Aapche2.2.*为例来实现此功能。

假设我们现在有shop和bbs两个目录,shop目录只能通过用户user1来访问,bbs目录则只能通过用户user2来访问,步骤如下:

(1)通过命令创建用户user1和user2,如下所示:

        C:\Apache2.2\bin>htpasswd -c C:/Apache2.2/htaccess user1
        C:\Apache2.2\bin>htpasswd C:/Apache2.2/htaccess user2

使用htpasswd命令创建用户,-c指定创建一个新的文件,C:/Apache2.2/htaccess是新文件的目录,user1是用户名,创建完成后,可以到C:/Apache2.2目录下打开htaccess文件查看用户信息,如下所示:

        user1:$apr1$aW5HEi2.$qUADQLr7cVGehl4NfWMFi1
        user2:$apr1$O8GattjZ$aGG.ix2qHl3Da5FGaQYhF0

(2)打开httpd.conf文件,找到下面的3个模块:

❑LoadModule auth_basic_module modules/mod_auth_basic.so

❑LoadModule authn_file_module modules/mod_authn_file.so

❑LoadModule authz_user_module modules/mod_authz_user.so

请确定上面3个加载模块的命令前的注释是去掉的。找到#Include conf/extra/httpd-autoindex.conf,去掉前面的注释(#)。在httpd-autoindex.conf中配置用户访问权限,修改完成后保存httpd.conf文件。

(3)进入conf/extra/目录,对文件httpd-autoindex.conf进行编辑,添加如下的代码:

        <Directory "C:/Apache2.2/htdocs/shop/">
            Options Indexes MultiViews
            AllowOverride None
            Order allow,deny
            Allow from all
        </Directory>
        <Directory "C:/Apache2.2/htdocs/shop/">
            AuthType Basic
            AuthName "please put into your name and password"
            AuthUserFile C:/Apache2.2/htaccess
            Require user user1
        </Directory>
        <Directory "C:/Apache2.2/htdocs/bbs/">
            Options Indexes MultiViews
            AllowOverride None
            Order allow,deny
            Allow from all
        </Directory>
        <Directory "C:/Apache2.2/htdocs/bbs/">
            AuthType Basic
            AuthName "please put into your name and password"
            AuthUserFile C:/Apache2.2/htaccess
            Require user user2
        </Directory>

代码中的关键部分说明如下:

❑AuthType:指定认证类型模型,一般常用的AuthType是“Basic/Digest”。这个认证需要用到认证模块mod_auth_basic/mod_auth_digest、认证支持模块mod_authn_file和认证授权模块mod_authz_user。

❑AuthName:指定验证登录框的提示信息。

❑AuthUserFile:指定验证信息文件的存放目录。

❑Require user:指定允许访问的用户,多个用户之间用空格分隔。

编辑完成后保存,重启Apache服务。

(4)输入网址http://localhost/shop进行测试,测试结果如图1-12所示。

图1-12 提示用户输入用户名和密码

如果输入有权限的用户名user1和密码,则进入访问目录,如图1-13所示。

图1-13 验证成功后进入显示页面

如果用户名或密码错误,访问该目录时会被拒绝。

1.8 小结

本书开篇之所以讲Apache是因为考虑到它的基础性及关键性,这是开始PHP之旅之前必修的一门课。本章主要讲解了Apache在实际工作中的应用,并对Apache配置文件的书写及其中的关键性模块进行了阐述。

如果大家对Apache还有更浓厚的兴趣,可以参阅Apache相关的专业书籍,这对以后从事基于服务器方面的管理和开发会有很大的帮助。