<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>我想网 &#187; Apache</title>
	<atom:link href="http://www.iwanna.cn/topics/develope/server/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.iwanna.cn</link>
	<description></description>
	<lastBuildDate>Sat, 31 Jul 2010 15:12:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WEB日志格式及分析工具</title>
		<link>http://www.iwanna.cn/archives/2010/07/25/4733/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/25/4733/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 14:27:12 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Tool]]></category>
		<category><![CDATA[WEB]]></category>
		<category><![CDATA[站长工具]]></category>
		<category><![CDATA[analysis]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4733</guid>
		<description><![CDATA[WEB日志是网站分析和网站数据数据整理最基础的数据，了解其格式和组成将有利于更好地进行数据的收集、处理和分析。
一、日志格式类型
目前常见的WEB日志格式主要由两类，一类是Apache的NCSA日志格式，另一类是IIS的W3C日志格式。NCSA格式又分为NCSA普  通日志格式（CLF）和NCSA扩展日志格式（ECLF）两类，目前最常用的是NCSA扩展日志格式（ECLF）及基于自定义类型的Apache日志格  式；而W3C扩展日志格式（ExLF）具备了更为丰富的输出信息，但目前的应用并不广泛，所以这里主要介绍的是NCSA扩展日志格式（ECLF）。

二、常见日志格式的组成
这是一个最常见的基于NCSA扩展日志格式（ECLF）的Apache日志样例：
58.61.164.141 – – [22/Feb/2010:09:51:46 +0800] “GET /   HTTP/1.1″ 206 6326 ” http://www.google.cn/search?q=webdataanalysis”   “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”
可以看到这个日志主要由以下几个部分组成：
访问主机（remotehost） 显示主机的IP地址或者已解析的域名。
标识符（Ident）由identd或直接由浏览器返回浏览者的EMAIL或其他唯一标示，因为涉及用户邮箱等 隐私信息，目前几乎所有的浏览器就取消了这项功能。
授权用户（authuser）用于记录浏览者进行身份验证时提供的名字，如果需要身份验证或者访问密码保护的信 息则这项不为空，但目前大多数网站的日志这项也都是为空的。
日期时间（date）一般的格式形如[22/Feb/2010:09:51:46  +0800]，即[日期/月份/年份:小时:分钟:秒钟 时区]，占用的的字符位数也基本固定。
请求（request）即在网站上通过何种方式获取了哪些信息，也是日志中较为重要的一项，主要包括以下三个部 分：

 请求类型（METHOD）常见的请求类型主要包括GET/POST/HEAD这三种；
 请求资源（RESOURCE）显示的是相应资源的URL，可以是某个网页的地址，也可以是网页上调用的图 片、动画、CSS等资源；
 协议版本号（PROTOCOL）显示协议及版本信息，通常是HTTP/1.1或HTTP/1.0。

状态码（status）用于表示服务器的响应状态，通常1xx的状态码表示继续消息；2xx表示请求成 功；3xx表示请求的重定向；4xx表示客户端错误；5xx表示服务器错误。
传输字节数（bytes）即该次请求中一共传输的字节数。
来源页面（referrer）用于表示浏览者在访问该页面之前所浏览的页面，只有从上一页面链接过来的请求才会 有该项输出，如果是新开的页面则该项为空。上例中来源页面是google，即用户从google搜索的结果中点击进入。
用户代理（agent）用于显示用户的详细信息，包括IP、OS、Bowser等。
三、日志格式扩展
apache日志格式可以自定义来配置其输出格式，常见的基于NCSA扩展日志格式（ECLF）自定义添加的包括域名 （domain）和cookie。其中域名在一个网站拥有二级域名或者子域名时，可以更好地区分日 志；而cookie可以作为用户的身份标识。其他具体的自定义信息详见：Custom  Log Formats
四、导入日志数据到MySQL中
访问分析是SEO的一项重要工作，但统计、分析工具毕竟功能是针对大众的，很多时候SEO需要一些特定的数据，是统计分析软件、程序所不能提供的。 这样，直接的Web日志分析就是最合适的了，日志中会记录每一个访问情况，只要按自己的意愿提取、组合，就能得到想要的数据。使用SQL语句分析是最方便 的，需要什么样的数据，只要使用相应的SQL命令就能实现。
导入Web日志到MySQL数据库的实现
1、修改Apache日志格式
修改Web日志格式为：
Logformat combined %&#62;a,%ui,%un,[%tl],”%rm %ru  HTTP/%rv”,%Hs,%h”,”%{User-Agent}&#62;h”,%Ss:%Sh
SQL需要导入的内容有特定的分隔符，Apache的日志默认是以空格分隔的，而有些内容（如状态码中的 200  610）也包含空格，这就无法准确的导入。将日志格式修改为以逗号分隔，就能准确的导入了。还可以根据自己的需要，取消日志格式中不需要的内容，减少日志 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">WEB</a>日志是网站分析和网站数据数据整理最基础的数据，了解其格式和组成将有利于更好地进行数据的收集、处理和分析。</p>
<p><strong>一、日志格式类型</strong></p>
<p>目前常见的<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">WEB</a>日志格式主要由两类，一类是<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的NCSA日志格式，另一类是IIS的W3C日志格式。NCSA格式又分为NCSA普  通日志格式（CLF）和NCSA扩展日志格式（ECLF）两类，目前最常用的是NCSA扩展日志格式（ECLF）及基于自定义类型的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>日志格  式；而W3C扩展日志格式（ExLF）具备了更为丰富的输出信息，但目前的应用并不广泛，所以这里主要介绍的是NCSA扩展日志格式（ECLF）。<br />
<span id="more-4733"></span><br />
<strong>二、常见日志格式的组成</strong></p>
<p>这是一个最常见的基于NCSA扩展日志格式（ECLF）的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>日志样例：</p>
<blockquote><p>58.61.164.141 – – [22/Feb/2010:09:51:46 +0800] “GET /   HTTP/1.1″ 206 6326 ” http://www.google.cn/search?q=webdataanalysis”   “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”</p></blockquote>
<p>可以看到这个日志主要由以下几个部分组成：</p>
<p><strong>访问主机</strong>（remotehost） 显示主机的IP地址或者已解析的域名。</p>
<p><strong>标识符</strong>（Ident）由identd或直接由浏览器返回浏览者的EMAIL或其他唯一标示，因为涉及用户邮箱等 隐私信息，目前几乎所有的浏览器就取消了这项功能。</p>
<p><strong>授权用户</strong>（authuser）用于记录浏览者进行身份验证时提供的名字，如果需要身份验证或者访问密码保护的信 息则这项不为空，但目前大多数网站的日志这项也都是为空的。</p>
<p><strong>日期时间</strong>（date）一般的格式形如[22/Feb/2010:09:51:46  +0800]，即[日期/月份/年份:小时:分钟:秒钟 时区]，占用的的字符位数也基本固定。</p>
<p><strong>请求</strong>（request）即在网站上通过何种方式获取了哪些信息，也是日志中较为重要的一项，主要包括以下三个部 分：</p>
<ul>
<li><strong> </strong>请求类型（METHOD）常见的请求类型主要包括GET/POST/HEAD这三种；</li>
<li><strong> </strong>请求资源（RESOURCE）显示的是相应资源的URL，可以是某个网页的地址，也可以是网页上调用的图 片、动画、CSS等资源；</li>
<li><strong> </strong>协议版本号（PROTOCOL）显示协议及版本信息，通常是HTTP/1.1或HTTP/1.0。</li>
</ul>
<p><strong>状态码</strong>（status）用于表示服务器的响应状态，通常1xx的状态码表示继续消息；2xx表示请求成 功；3xx表示请求的重定向；4xx表示客户端错误；5xx表示服务器错误。</p>
<p><strong>传输字节数</strong>（bytes）即该次请求中一共传输的字节数。</p>
<p><strong>来源页面</strong>（referrer）用于表示浏览者在访问该页面之前所浏览的页面，只有从上一页面链接过来的请求才会 有该项输出，如果是新开的页面则该项为空。上例中来源页面是google，即用户从google搜索的结果中点击进入。</p>
<p><strong>用户代理</strong>（agent）用于显示用户的详细信息，包括IP、OS、Bowser等。</p>
<p><strong>三、日志格式扩展</strong></p>
<p><a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">apache</a>日志格式可以自定义来配置其输出格式，常见的基于NCSA扩展日志格式（ECLF）自定义添加的包括<strong>域名 （domain）</strong>和<strong>cookie</strong>。其中域名在一个网站拥有二级域名或者子域名时，可以更好地区分日 志；而cookie可以作为用户的身份标识。其他具体的自定义信息详见：<a href="http://httpd.apache.org/docs/2.0/mod/mod_log_config.html#formats" target="_blank">Custom  Log Formats</a></p>
<p><strong>四、导入日志数据到MySQL中</strong></p>
<p>访问分析是SEO的一项重要工作，但统计、分析工具毕竟功能是针对大众的，很多时候SEO需要一些特定的数据，是统计分析软件、程序所不能提供的。 这样，直接的<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">Web</a>日志分析就是最合适的了，日志中会记录每一个访问情况，只要按自己的意愿提取、组合，就能得到想要的数据。使用SQL语句分析是最方便 的，需要什么样的数据，只要使用相应的SQL命令就能实现。</p>
<p>导入<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">Web</a>日志到MySQL数据库的实现</p>
<p>1、修改<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>日志格式</p>
<p>修改<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">Web</a>日志格式为：</p>
<blockquote><p>Logformat combined %&gt;a,%ui,%un,[%tl],”%rm %ru  HTTP/%rv”,%Hs,%h”,”%{User-Agent}&gt;h”,%Ss:%Sh</p></blockquote>
<p>SQL需要导入的内容有特定的分隔符，<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的日志默认是以空格分隔的，而有些内容（如状态码中的 200  610）也包含空格，这就无法准确的导入。将日志格式修改为以逗号分隔，就能准确的导入了。还可以根据自己的需要，取消日志格式中不需要的内容，减少日志 文件大小。</p>
<p>2、建立MySQL数据表</p>
<blockquote><p>drop table if exists weblog;<br />
create table weblog (<br />
id int unsigned auto_increment PRIMARY KEY not null,<br />
l_date date,<br />
l_time time,<br />
c_ip varchar(15),<br />
s_ip varchar(15),<br />
s_port varchar(5),<br />
method varchar(10),<br />
path varchar(255),<br />
query varchar(255),<br />
status varchar(3),<br />
domain varchar(50),<br />
system varchar(200)<br />
);</p></blockquote>
<p>注：上面只是一个MySQL数据表结构范例，没有与上一步日志格式对应，请勿直接复制使用！</p>
<p>新建一个数据库，数据表结构与日志格式对应起来。</p>
<p>3、导入日志到MySQL中</p>
<blockquote><p>LOAD DATA INFILE  ’/日志位置/日志文件’  INTO TABLE weblog FIELDS  TERMINATED BY ‘,’;</p></blockquote>
<p>weblog 对应上面的数据表名。</p>
<p>另外，乐思蜀从网上找到一个将IIS日志导入到MySQL数据库的.pl程序，需要的<a href="http://www.box.net/shared/dnjdq4a6zc" target="_blank">点这里下载</a>（Readme.txt为使用说明）。</p>
<p>五、常用日志分析工具</p>
<p>1.awstats</p>
<p>2.analog</p>
<p>3.webalizer</p>
<p>4.PHPMyVisites</p>
<p>本文参考：</p>
<p>http://webdataanalysis.net/reference-and-source/weblog-format/</p>
<p>http://www.lesishu.com/net/import-weblog-to-mysql/</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/25/4733/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/25/4733/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/25/4733/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/25/4733/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/25/4733/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/tags/analysis/" title="analysis" rel="tag nofollow">analysis</a>, <a href="http://www.iwanna.cn/topics/develope/server/apache/" title="Apache" rel="tag nofollow">Apache</a>, <a href="http://www.iwanna.cn/topics/develope/server/" title="Server" rel="tag nofollow">Server</a>, <a href="http://www.iwanna.cn/topics/software/tool/" title="Tool" rel="tag nofollow">Tool</a>, <a href="http://www.iwanna.cn/tags/tool/" title="Tool" rel="tag nofollow">Tool</a>, <a href="http://www.iwanna.cn/tags/web/" title="Web" rel="tag nofollow">Web</a>, <a href="http://www.iwanna.cn/topics/ui/web-ui/" title="WEB" rel="tag nofollow">WEB</a>, <a href="http://www.iwanna.cn/topics/develope/stationmaster/" title="站长工具" rel="tag nofollow">站长工具</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2010/07/27/4756/" title="如何量化用户体验 (2010年07月27日)">如何量化用户体验</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/05/16/3180/" title="关于交互设计师需要画的线框图 (2010年05月16日)">关于交互设计师需要画的线框图</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/02/4325/" title="做网站常用工具下载与介绍 (2010年07月2日)">做网站常用工具下载与介绍</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/07/09/1956/" title="5个整站下载工具 (2009年07月9日)">5个整站下载工具</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/01/4285/" title="50 个Web 设计师的超便利工具[下] (2010年07月1日)">50 个Web 设计师的超便利工具[下]</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/01/4284/" title="50 个Web 设计师的超便利工具[上] (2010年07月1日)">50 个Web 设计师的超便利工具[上]</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/24/4719/" title="20免费的Web UI元素工具箱和模具 (2010年07月24日)">20免费的Web UI元素工具箱和模具</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/06/15/1819/" title="20个使Web开发变得更轻松的制作工具 (2009年06月15日)">20个使Web开发变得更轻松的制作工具</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/16/446/" title="2009年 非盈利机构必备的10大Web2.0工具 (2009年04月16日)">2009年 非盈利机构必备的10大Web2.0工具</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/24/821/" title="15个最受Web开发者欢迎的文本编辑器 (2009年04月24日)">15个最受Web开发者欢迎的文本编辑器</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/25/4733/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache中 RewriteRule 规则参数介绍</title>
		<link>http://www.iwanna.cn/archives/2009/10/19/2321/</link>
		<comments>http://www.iwanna.cn/archives/2009/10/19/2321/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 07:50:27 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=2321</guid>
		<description><![CDATA[Apache模 块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操 作机制。此URL操作可以依赖于各种测试，比如服务器变量、环境变量、HTTP头、时间标记，甚至各种格式的用于匹配URL组成部分的查找数据库。
此模块可以操作URL的所有部分(包括路径信息部分)，在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效，还可以生成最终请求字符串。此重写操作的结果可以是内部子处理，也可以是外部请求的转向，甚至还可以是内部代理处理。

这里着重介绍一下 RewriteRule 的规则以及参数说明。RewriteRule指令是重写引擎的根本。此指令可以多次使用。每个指令定义一个简单的重写规则。这些规则的定义顺序尤为重要——在运行时，规则是按这个顺序逐一生效的。
RewriteRule Pattern Substitution [flags]
Pattern是一个作用于当前URL的perl兼容的正则表达式。&#8221;当前URL&#8221;是指该规则生效时刻的URL的值。它可能与被请求的URL截然不同，因为其他规则可能在此之前已经发生匹配并对它做了改动。
Substitution是当原始URL与Pattern相匹配时，用来替代(或替换)的字符串。除了纯文本，还可以包含：
对Pattern的反向引用($N)
对最后匹配的RewriteCond的反向引用(%N)
规则条件测试字符串(%{VARNAME})中的服务器变量
映射函数调用(${mapname:key&#124;default})
[flags]标记作为RewriteRule指令的第三个参数，是一个包含以逗号分隔的下列标记的列表：
&#8216;chain&#124;C&#8217;(链接下一规则)
此标记使当前规则与下一个规则相链接。它产生这样的效果：如果一个规则被匹配，则继续处理其后继规则，也就是这个标记不起作用；如果该规则不被匹配，则其 后继规则将被跳过。比如，在一个目录级规则中执行一个外部重定向时，你可能需要删除&#8221;.www&#8221;(此处不应该出现&#8221;.www&#8221;)。
&#8216;cookie&#124;CO=NAME:VAL:domain[:lifetime[:path]]&#8217;(设置cookie)
在客户端设置一个cookie。cookie的名称是NAME，值是VAL。domain是该cookie的域，比如&#8217;.apache.org&#8217;，可选的lifetime是cookie的有效期(分钟)，可选的path是cookie的路径。
&#8216;env&#124;E=VAR:VAL&#8217;(设置环境变量)
此标记将环境变量VAR的值为VAL，VAL可以包含可扩展的正则表达式反向引用($N和%N)。此标记可以多次使用以设置多个变量。这些变量可以在其后 许多情况下被间接引用，通常是在XSSI(&#60;!&#8211;#echo var=&#8221;VAR&#8221;&#8211;&#62;)或CGI($ENV{&#8216;VAR&#8217;})中，也可以在后继的RewriteCond指令的CondPattern参数中通 过%{ENV:VAR}引用。使用它可以记住从URL中剥离的信息。
&#8216;forbidden&#124;F&#8217;(强制禁止URL)
强制禁止当前URL，也就是立即反馈一个HTTP响应码403(被禁止的)。使用这个标记，可以链接若干个RewriteConds来有条件地阻塞某些URL。
&#8216;gone&#124;G&#8217;(强制废弃URL)
强制当前URL为已废弃，也就是立即反馈一个HTTP响应码410(已废弃的)。使用这个标记，可以标明页面已经被废弃而不存在了。
&#8216;handler&#124;H=Content-handler&#8217;(强制指定内容处理器)
强自制定目标文件的内容处理器为Content-handler。例如，用来模拟mod_alias模块的ScriptAlias指令，以强制映射文件夹内的所有文件都由&#8221;cgi-script&#8221;处理器处理。
&#8216;last&#124;L&#8217;(结尾规则)
立即停止重写操作，并不再应用其他重写规则。它对应于Perl中的last命令或C语言中的break命令。这个标记用于阻止当前已被重写的URL被后继规则再次重写。例如，使用它可以重写根路径的URL(&#8216;/&#8217;)为实际存在的URL(比如：&#8217;/e/www/&#8217;)。
&#8216;next&#124;N&#8217;(从头再来)
重新执行重写操作(从第一个规则重新开始)。此时再次进行处理的URL已经不是原始的URL了，而是经最后一个重写规则处理过的URL。它对应于Perl 中的next命令或C语言中的continue命令。此标记可以重新开始重写操作(立即回到循环的开头)。但是要小心，不要制造死循环！
&#8216;nocase&#124;NC&#8217;(忽略大小写)
它使Pattern忽略大小写，也就是在Pattern与当前URL匹配时，&#8217;A-Z&#8217;和&#8217;a-z&#8217;没有区别。
&#8216;noescape&#124;NE&#8217;(在输出中不对URI进行转义)
此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下，特殊字符(&#8216;%&#8217;, &#8216;$&#8217;, &#8216;;&#8217;等)会被转义为等值的十六进制编码(&#8216;%25&#8242;, &#8216;%24&#8242;, &#8216;%3B&#8217;等)。此标记可以阻止这样的转义，以允许百分号等符号出现在输出中，比如：
RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
可以使&#8217;/foo/zed转向到一个安全的请求&#8217;/bar?arg=P1=zed&#8217;。
&#8216;nosubreq&#124;NS&#8217;(不对内部子请求进行处理)
在当前请求是一个内部子请求时，此标记强制重写引擎跳过该重写规则。比如，在mod_include试图搜索目录默认文件(index.xxx) 时，Apache会在内部产生子请求。对于子请求，重写规则不一定有用，而且如果整个规则集都起作用，它甚至可能会引发错误。所以，可以用这个标记来排除 某些规则。
使用原则：如果你为URL添加了CGI脚本前缀，以强制它们由CGI脚本处理，但对子请求处理的出错率(或者资源开销)很高，在这种情况下，可以使用这个标记。
&#8216;proxy&#124;P&#8217;(强制为代理)
此标记使替换成分被内部地强制作为代理请求发送，并立即中断重写处理，然后把处理移交给mod_proxy模块。你必须确保此替换串是一个能够被 mod_proxy处理的有效URI(比如以http://hostname开头)，否则将得到一个代理模块返回的错误。使用这个标记，可以把某些远程成 分映射到本地服务器域名空间，从而增强了ProxyPass指令的功能。
注意：要使用这个功能，必须已经启用了mod_proxy模块。
&#8216;passthrough&#124;PT&#8217;(移交给下一个处理器)
此标记强制重写引擎将内部request_rec结构中的uri字段设置为filename字段的值，这个小小的修改使得RewriteRule指令的输 出能够被(从URI转换到文件名的)Alias, ScriptAlias, Redirect等指令进行后续处理[原文：This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias, ScriptAlias, Redirect, and other directives from various URI-to-filename translators.]。举一个能说明其含义的例子： [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>模 块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操 作机制。此URL操作可以依赖于各种测试，比如服务器变量、环境变量、HTTP头、时间标记，甚至各种格式的用于匹配URL组成部分的查找数据库。</p>
<p>此模块可以操作URL的所有部分(包括路径信息部分)，在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效，还可以生成最终请求字符串。此重写操作的结果可以是内部子处理，也可以是外部请求的转向，甚至还可以是内部代理处理。<br />
<span id="more-2321"></span><br />
这里着重介绍一下 RewriteRule 的规则以及参数说明。RewriteRule指令是重写引擎的根本。此指令可以多次使用。每个指令定义一个简单的重写规则。这些规则的定义顺序尤为重要——在运行时，规则是按这个顺序逐一生效的。</p>
<pre>RewriteRule Pattern Substitution [flags]</pre>
<p>Pattern是一个作用于当前URL的perl兼容的正则表达式。&#8221;当前URL&#8221;是指该规则生效时刻的URL的值。它可能与被请求的URL截然不同，因为其他规则可能在此之前已经发生匹配并对它做了改动。</p>
<p>Substitution是当原始URL与Pattern相匹配时，用来替代(或替换)的字符串。除了纯文本，还可以包含：<br />
对Pattern的反向引用($N)<br />
对最后匹配的RewriteCond的反向引用(%N)<br />
规则条件测试字符串(%{VARNAME})中的服务器变量<br />
映射函数调用(${mapname:key|default})</p>
<p>[flags]标记作为RewriteRule指令的第三个参数，是一个包含以逗号分隔的下列标记的列表：<br />
<span>&#8216;chain|C&#8217;(链接下一规则)</span><br />
此标记使当前规则与下一个规则相链接。它产生这样的效果：如果一个规则被匹配，则继续处理其后继规则，也就是这个标记不起作用；如果该规则不被匹配，则其 后继规则将被跳过。比如，在一个目录级规则中执行一个外部重定向时，你可能需要删除&#8221;.www&#8221;(此处不应该出现&#8221;.www&#8221;)。<br />
<span>&#8216;cookie|CO=NAME:VAL:domain[:lifetime[:path]]&#8217;(设置cookie)</span><br />
在客户端设置一个cookie。cookie的名称是NAME，值是VAL。domain是该cookie的域，比如&#8217;.<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">apache</a>.org&#8217;，可选的lifetime是cookie的有效期(分钟)，可选的path是cookie的路径。<br />
<span>&#8216;env|E=VAR:VAL&#8217;(设置环境变量)</span><br />
此标记将环境变量VAR的值为VAL，VAL可以包含可扩展的正则表达式反向引用($N和%N)。此标记可以多次使用以设置多个变量。这些变量可以在其后 许多情况下被间接引用，通常是在XSSI(&lt;!&#8211;#echo var=&#8221;VAR&#8221;&#8211;&gt;)或CGI($ENV{&#8216;VAR&#8217;})中，也可以在后继的RewriteCond指令的CondPattern参数中通 过%{ENV:VAR}引用。使用它可以记住从URL中剥离的信息。<br />
<span>&#8216;forbidden|F&#8217;(强制禁止URL)</span><br />
强制禁止当前URL，也就是立即反馈一个HTTP响应码403(被禁止的)。使用这个标记，可以链接若干个RewriteConds来有条件地阻塞某些URL。<br />
<span>&#8216;gone|G&#8217;(强制废弃URL)</span><br />
强制当前URL为已废弃，也就是立即反馈一个HTTP响应码410(已废弃的)。使用这个标记，可以标明页面已经被废弃而不存在了。<br />
<span>&#8216;handler|H=Content-handler&#8217;(强制指定内容处理器)</span><br />
强自制定目标文件的内容处理器为Content-handler。例如，用来模拟mod_alias模块的ScriptAlias指令，以强制映射文件夹内的所有文件都由&#8221;cgi-script&#8221;处理器处理。<br />
<span>&#8216;last|L&#8217;(结尾规则)</span><br />
立即停止重写操作，并不再应用其他重写规则。它对应于Perl中的last命令或C语言中的break命令。这个标记用于阻止当前已被重写的URL被后继规则再次重写。例如，使用它可以重写根路径的URL(&#8216;/&#8217;)为实际存在的URL(比如：&#8217;/e/www/&#8217;)。<br />
<span>&#8216;next|N&#8217;(从头再来)</span><br />
重新执行重写操作(从第一个规则重新开始)。此时再次进行处理的URL已经不是原始的URL了，而是经最后一个重写规则处理过的URL。它对应于Perl 中的next命令或C语言中的continue命令。此标记可以重新开始重写操作(立即回到循环的开头)。但是要小心，不要制造死循环！<br />
<span>&#8216;nocase|NC&#8217;(忽略大小写)</span><br />
它使Pattern忽略大小写，也就是在Pattern与当前URL匹配时，&#8217;A-Z&#8217;和&#8217;a-z&#8217;没有区别。<br />
<span>&#8216;noescape|NE&#8217;(在输出中不对URI进行转义)</span><br />
此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下，特殊字符(&#8216;%&#8217;, &#8216;$&#8217;, &#8216;;&#8217;等)会被转义为等值的十六进制编码(&#8216;%25&#8242;, &#8216;%24&#8242;, &#8216;%3B&#8217;等)。此标记可以阻止这样的转义，以允许百分号等符号出现在输出中，比如：</p>
<pre>RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]</pre>
<p>可以使&#8217;/foo/zed转向到一个安全的请求&#8217;/bar?arg=P1=zed&#8217;。<br />
<span>&#8216;nosubreq|NS&#8217;(不对内部子请求进行处理)</span><br />
在当前请求是一个内部子请求时，此标记强制重写引擎跳过该重写规则。比如，在mod_include试图搜索目录默认文件(index.xxx) 时，<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>会在内部产生子请求。对于子请求，重写规则不一定有用，而且如果整个规则集都起作用，它甚至可能会引发错误。所以，可以用这个标记来排除 某些规则。<br />
使用原则：如果你为URL添加了CGI脚本前缀，以强制它们由CGI脚本处理，但对子请求处理的出错率(或者资源开销)很高，在这种情况下，可以使用这个标记。<br />
<span>&#8216;proxy|P&#8217;(强制为代理)</span><br />
此标记使替换成分被内部地强制作为代理请求发送，并立即中断重写处理，然后把处理移交给mod_proxy模块。你必须确保此替换串是一个能够被 mod_proxy处理的有效URI(比如以http://hostname开头)，否则将得到一个代理模块返回的错误。使用这个标记，可以把某些远程成 分映射到本地服务器域名空间，从而增强了ProxyPass指令的功能。<br />
注意：要使用这个功能，必须已经启用了mod_proxy模块。<br />
<span>&#8216;passthrough|PT&#8217;(移交给下一个处理器)</span><br />
此标记强制重写引擎将内部request_rec结构中的uri字段设置为filename字段的值，这个小小的修改使得RewriteRule指令的输 出能够被(从URI转换到文件名的)Alias, ScriptAlias, Redirect等指令进行后续处理[原文：This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias, ScriptAlias, Redirect, and other directives from various URI-to-filename translators.]。举一个能说明其含义的例子： 如果要将/abc重写为/def， 然后再使用mod_alias将/def转换为/ghi，可以这样：</p>
<pre>RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi</pre>
<p>如果省略了PT标记，虽然将uri=/abc/&#8230;重写为filename=/def/&#8230;的部分运作正常，但是后续的mod_alias在试图将URI转换到文件名时会遭遇失效。<br />
注意：如果需要混合使用多个将URI转换到文件名的模块时，就必须使用这个标记。。此处混合使用mod_alias和mod_rewrite就是个典型的例子。<br />
<span>&#8216;qsappend|QSA&#8217;(追加查询字符串)</span><br />
此标记强制重写引擎在已有的替换字符串中追加一个查询字符串，而不是简单的替换。如果需要通过重写规则在请求串中增加信息，就可以使用这个标记。<br />
<span>&#8216;redirect|R [=code]&#8216;(强制重定向)</span><br />
若Substitution以http://thishost[:thisport]/(使新的URL成为一个URI)开头，可以强制性执行一个外部重定 向。如果没有指定code，则产生一个HTTP响应码302(临时性移动)。如果需要使用在300-400范围内的其他响应代码，只需在此指定即可(或使 用下列符号名称之一：temp(默认), permanent, seeother)。使用它可以把规范化的URL反馈给客户端，如将&#8221;/~&#8221;重写为&#8221;/u/&#8221;，或始终对/u/user加上斜杠，等等。<br />
注意：在使用这个标记时，必须确保该替换字段是一个有效的URL。否则，它会指向一个无效的位置！并且要记住，此标记本身只是对URL加上 http://thishost[:thisport]/前缀，重写操作仍然会继续进行。通常，你还会希望停止重写操作而立即重定向，那么就还需要使用 &#8216;L&#8217;标记。<br />
<span>&#8217;skip|S=num&#8217;(跳过后继规则)</span><br />
此标记强制重写引擎跳过当前匹配规则之后的num个规则。它可以模拟if-then-else结构：最后一个规则是then从句，而被跳过的skip=N个规则是else从句。注意：它和&#8217;chain|C&#8217;标记是不同的！<br />
<span>&#8216;type|T=MIME-type&#8217;(强制MIME类型)</span><br />
强制目标文件的MIME类型为MIME-type，可以用来基于某些特定条件强制设置内容类型。比如，下面的指令可以让.php文件在以.phps扩展名 调用的情况下由mod_php按照PHP源代码的MIME类型(application/x-httpd-php-source)显示：</p>
<pre>RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]</pre>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/10/19/2321/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/10/19/2321/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/10/19/2321/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/10/19/2321/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/10/19/2321/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/server/apache/" title="Apache" rel="tag nofollow">Apache</a>, <a href="http://www.iwanna.cn/tags/apache/" title="Apache" rel="tag nofollow">Apache</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/10/09/2276/" title="深入理解Apache的mod_rewrite (2009年10月9日)">深入理解Apache的mod_rewrite</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/10/19/2318/" title="Apache中 RewriteCond 规则参数介绍 (2009年10月19日)">Apache中 RewriteCond 规则参数介绍</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/10/19/2321/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache中 RewriteCond 规则参数介绍</title>
		<link>http://www.iwanna.cn/archives/2009/10/19/2318/</link>
		<comments>http://www.iwanna.cn/archives/2009/10/19/2318/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 07:36:40 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=2318</guid>
		<description><![CDATA[Apache模块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操 作机制。此URL操作可以依赖于各种测试，比如服务器变量、环境变量、HTTP头、时间标记，甚至各种格式的用于匹配URL组成部分的查找数据库。
此模块可以操作URL的所有部分(包括路径信息部分)，在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效，还可以生成最终请求字符串。此重写操作的结果可以是内部子处理，也可以是外部请求的转向，甚至还可以是内部代理处理。

这里着重介绍一下 RewriteCond 的规则以及参数说明。RewriteCond指令定义了规则生效的条件，即在一个RewriteRule指令之前可以有一个或多个RewriteCond 指令。条件之后的重写规则仅在当前URI与Pattern匹配并且满足此处的条件(TestString能够与CondPattern匹配)时才会起作 用。
【说明 】定义重写发生的条件
【语法】 RewriteCond TestString CondPattern [flags]
【作用域】 server config, virtual host, directory, .htaccess
【覆盖项】 FileInfo
【状态】 扩展(E)
【模块】 mod_rewrite
TestString是一个纯文本的字符串，但是还可以包含下列可扩展的成分：
1、RewriteRule反向引用 ，引用方法是：$N (0 &#60;= N &#60;= 9)引用当前(带有若干RewriteRule指令的)RewriteCond中的与Pattern匹配的分组成分(圆括号!)。
2、RewriteCond反向引用 ，引用方法是：%N (1 &#60;= N &#60;= 9)引用当前若干RewriteCond条件中最后符合的条件中的分组成分(圆括号!)。
3、RewriteMap扩展 ，引用方法是：${mapname:key&#124;default} 细节请参见RewriteMap 指令。
4、服务器变量 ，引用方法是：%{NAME_OF_VARIABLE} NAME_OF_VARIABLE可以是下表列出的字符串之一：



HTTP头
连接与请求



HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPT
REMOTE_ADDR
REMOTE_HOST
REMOTE_PORT
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE



服务器自身
日期和时间
其它


DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ
HTTPS



这些变量都对应于类似命名的HTTP MIME头、Apache服务器的C变量、Unix系统中的struct tm字段，其中的大多数在其他的手册或者CGI规范中都有说明。 其中为mod_rewrite所特有的变量如下：
IS_SUBREQ
如果正在处理的请求是一个子请求，它将包含字符串&#8221;true&#8221;，否则就是&#8221;false&#8221;。模块为了解析URI中的附加文件，可能会产生子请求。
API_VERSION
这是正在使用中的Apache模块API(服务器和模块之间内部接口)的版本， 其定义位于include/ap_mmn.h中。此模块API版本对应于正在使用的Apache的版本(比如在Apache 1.3.14的发行版中这个值是19990320:10)。 通常，对它感兴趣的是模块的开发者。
THE_REQUEST
这是由浏览器发送的完整的HTTP请求行(比如：&#8221;GET /index.html HTTP/1.1&#8243;)。它不包含任何浏览器发送的其它头信息。
REQUEST_URI
这是在HTTP请求行中所请求的资源(比如上述例子中的&#8221;/index.html&#8221;)。
REQUEST_FILENAME
这是与请求相匹配的完整的本地文件系统的文件路径名。
HTTPS
如果连接使用了SSL/TLS，它将包含字符串&#8221;on&#8221;，否则就是&#8221;off&#8221;(无论mod_ssl是否已经加载，该变量都可以安全的使用)。
其它注意事项：
1、SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的——即Apache服务器内部的request_rec结构中的 filename字段。 第一个就是大家都知道的CGI变量名，而第二个则是REQUEST_URI(request_rec结构中的uri字段)的一个副本。
2、特殊形式：%{ENV:variable} ，其中的variable可以是任意环境变量。它是通过查找Apache内部结构或者(如果没找到的话)由Apache服务器进程通过getenv()得到的。
3、特殊形式：%{SSL:variable} ，其中的variable可以是一个SSL环境变量的名字，无论mod_ssl模块是否已经加载都可以使用(未加载时为空字符串)。比如：%{SSL:SSL_CIPHER_USEKEYSIZE}将会被替换为128。
4、特殊形式：%{HTTP:header} ，其中的header可以是任意HTTP MIME头的名称。它总是可以通过查找HTTP请求而得到。比如：%{HTTP:Proxy-Connection}将被替换为Proxy-Connection:HTTP头的值。
5、预设形式：%{LA-U:variable} ，variable的最终值在执行一个内部(基于URL的)子请求后确定。 当需要使用一个目前未知但是会在之后的过程中设置的变量的时候，就可以使用这个方法。例如，需要在服务器级配置(httpd.conf文件)中根据 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>模块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操 作机制。此URL操作可以依赖于各种测试，比如服务器变量、环境变量、HTTP头、时间标记，甚至各种格式的用于匹配URL组成部分的查找数据库。</p>
<p>此模块可以操作URL的所有部分(包括路径信息部分)，在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效，还可以生成最终请求字符串。此重写操作的结果可以是内部子处理，也可以是外部请求的转向，甚至还可以是内部代理处理。<br />
<span id="more-2318"></span><br />
这里着重介绍一下 RewriteCond 的规则以及参数说明。RewriteCond指令定义了规则生效的条件，即在一个RewriteRule指令之前可以有一个或多个RewriteCond 指令。条件之后的重写规则仅在当前URI与Pattern匹配并且满足此处的条件(TestString能够与CondPattern匹配)时才会起作 用。</p>
<blockquote><p>【说明 】定义重写发生的条件<br />
【语法】 RewriteCond TestString CondPattern [flags]<br />
【作用域】 server config, virtual host, directory, .htaccess<br />
【覆盖项】 FileInfo<br />
【状态】 扩展(E)<br />
【模块】 mod_rewrite</p></blockquote>
<p>TestString是一个纯文本的字符串，但是还可以包含下列可扩展的成分：<br />
1、<span>RewriteRule反向引用</span> ，引用方法是：<span>$N</span> (0 &lt;= N &lt;= 9)引用当前(带有若干RewriteRule指令的)RewriteCond中的与Pattern匹配的分组成分(圆括号!)。<br />
2、<span>RewriteCond反向引用</span> ，引用方法是：<span>%N</span> (1 &lt;= N &lt;= 9)引用当前若干RewriteCond条件中最后符合的条件中的分组成分(圆括号!)。<br />
3、<span>RewriteMap扩展</span> ，引用方法是：<span>${mapname:key|default}</span> 细节请参见<a href="http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_rewrite.html#mapfunc" target="_blank">RewriteMap 指令</a>。<br />
4、<span>服务器变量</span> ，引用方法是：<span>%{NAME_OF_VARIABLE}</span> NAME_OF_VARIABLE可以是下表列出的字符串之一：</p>
<table border="1" cellspacing="0" cellpadding="3" bordercolor="#aaaaaa">
<tbody>
<tr>
<th>HTTP头</th>
<th>连接与请求</th>
<th></th>
</tr>
<tr>
<td>HTTP_USER_AGENT<br />
HTTP_REFERER<br />
HTTP_COOKIE<br />
HTTP_FORWARDED<br />
HTTP_HOST<br />
HTTP_PROXY_CONNECTION<br />
HTTP_ACCEPT</td>
<td>REMOTE_ADDR<br />
REMOTE_HOST<br />
REMOTE_PORT<br />
REMOTE_USER<br />
REMOTE_IDENT<br />
REQUEST_METHOD<br />
SCRIPT_FILENAME<br />
PATH_INFO<br />
QUERY_STRING<br />
AUTH_TYPE</td>
<td></td>
</tr>
<tr>
<th>服务器自身</th>
<th>日期和时间</th>
<th>其它</th>
</tr>
<tr>
<td>DOCUMENT_ROOT<br />
SERVER_ADMIN<br />
SERVER_NAME<br />
SERVER_ADDR<br />
SERVER_PORT<br />
SERVER_PROTOCOL<br />
SERVER_SOFTWARE</td>
<td>TIME_YEAR<br />
TIME_MON<br />
TIME_DAY<br />
TIME_HOUR<br />
TIME_MIN<br />
TIME_SEC<br />
TIME_WDAY<br />
TIME</td>
<td>API_VERSION<br />
THE_REQUEST<br />
REQUEST_URI<br />
REQUEST_FILENAME<br />
IS_SUBREQ<br />
HTTPS</td>
</tr>
</tbody>
</table>
<p>这些变量都对应于类似命名的HTTP MIME头、<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>服务器的C变量、Unix系统中的struct tm字段，其中的大多数在其他的手册或者CGI规范中都有说明。 其中为mod_rewrite所特有的变量如下：</p>
<blockquote><p>IS_SUBREQ<br />
如果正在处理的请求是一个子请求，它将包含字符串&#8221;true&#8221;，否则就是&#8221;false&#8221;。模块为了解析URI中的附加文件，可能会产生子请求。<br />
API_VERSION<br />
这是正在使用中的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>模块API(服务器和模块之间内部接口)的版本， 其定义位于include/ap_mmn.h中。此模块API版本对应于正在使用的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的版本(比如在<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a> 1.3.14的发行版中这个值是19990320:10)。 通常，对它感兴趣的是模块的开发者。<br />
THE_REQUEST<br />
这是由浏览器发送的完整的HTTP请求行(比如：&#8221;GET /index.html HTTP/1.1&#8243;)。它不包含任何浏览器发送的其它头信息。<br />
REQUEST_URI<br />
这是在HTTP请求行中所请求的资源(比如上述例子中的&#8221;/index.html&#8221;)。<br />
REQUEST_FILENAME<br />
这是与请求相匹配的完整的本地文件系统的文件路径名。<br />
HTTPS<br />
如果连接使用了SSL/TLS，它将包含字符串&#8221;on&#8221;，否则就是&#8221;off&#8221;(无论<a href="http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_ssl.html" target="_blank">mod_ssl</a>是否已经加载，该变量都可以安全的使用)。</p></blockquote>
<p>其它注意事项：<br />
1、SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的——即<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>服务器内部的request_rec结构中的 filename字段。 第一个就是大家都知道的CGI变量名，而第二个则是REQUEST_URI(request_rec结构中的uri字段)的一个副本。<br />
2、特殊形式：%{ENV:variable} ，其中的variable可以是任意环境变量。它是通过查找<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>内部结构或者(如果没找到的话)由<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>服务器进程通过getenv()得到的。<br />
3、特殊形式：%{SSL:variable} ，其中的variable可以是一个<a href="http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_ssl.html#envvars" target="_blank">SSL环境变量</a>的名字，无论<a href="http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_ssl.html" target="_blank">mod_ssl</a>模块是否已经加载都可以使用(未加载时为空字符串)。比如：%{SSL:SSL_CIPHER_USEKEYSIZE}将会被替换为128。<br />
4、特殊形式：%{HTTP:header} ，其中的header可以是任意HTTP MIME头的名称。它总是可以通过查找HTTP请求而得到。比如：%{HTTP:Proxy-Connection}将被替换为Proxy-Connection:HTTP头的值。<br />
5、预设形式：%{LA-U:variable} ，variable的最终值在执行一个内部(基于URL的)子请求后确定。 当需要使用一个目前未知但是会在之后的过程中设置的变量的时候，就可以使用这个方法。例如，需要在服务器级配置(httpd.conf文件)中根据 REMOTE_USER变量进行重写， 就必须使用%{LA-U:REMOTE_USER}。因为此变量是由URL重写(mod_rewrite)步骤之后的认证步骤设置的。 但是另一方面，因为mod_rewrite是通过API修正步骤来实现目录级(.htaccess文件)配置的， 而认证步骤先于API修正步骤，所以可以用%{REMOTE_USER}。<br />
6、预设形式：%{LA-F:variable} ，variable的最终值在执行一个内部(基于文件名的)子请求后确定。 大多数情况下和上述的LA-U是相同的。</p>
<p>CondPattern是条件模式，即一个应用于当前TestString实例的正则表达式。TestString将被首先计算，然后再与CondPattern匹配。</p>
<p><span>注意：</span>CondPattern是一个perl兼容的正则表达式，但是还有若干增补：<br />
1、可以在CondPattern串的开头使用&#8217;!'(惊叹号)来指定<span>不匹配</span>。<br />
2、CondPatterns有若干特殊的变种。除了正则表达式的标准用法，还有下列用法：</p>
<blockquote><p>&#8216;<span>&lt;CondPattern</span>&#8216;(词典顺序的小于)<br />
将CondPattern视为纯字符串，与TestString按词典顺序进行比较。如果TestString小于CondPattern则为真。<br />
&#8216;<span>&gt;CondPattern</span>&#8216;(词典顺序的大于)<br />
将CondPattern视为纯字符串，与TestString按词典顺序进行比较。如果TestString大于CondPattern则为真。<br />
&#8216;<span>=CondPattern</span>&#8216;(词典顺序的等于)<br />
将CondPattern视为纯字符串，与TestString按词典顺序进行比较。如果TestString等于CondPattern(两个字符串逐 个字符地完全相等)则为真。如果CondPattern是&#8221;"(两个双引号)，则TestString将与空字符串进行比较。<br />
&#8216;<span>-d</span>&#8216;(目录)<br />
将TestString视为一个路径名并测试它是否为一个存在的目录。<br />
&#8216;<span>-f</span>&#8216;(常规文件)<br />
将TestString视为一个路径名并测试它是否为一个存在的常规文件。<br />
&#8216;<span>-s</span>&#8216;(非空的常规文件)<br />
将TestString视为一个路径名并测试它是否为一个存在的、尺寸大于0的常规文件。<br />
&#8216;<span>-l</span>&#8216;(符号连接)<br />
将TestString视为一个路径名并测试它是否为一个存在的符号连接。<br />
&#8216;<span>-x</span>&#8216;(可执行)<br />
将TestString视为一个路径名并测试它是否为一个存在的、具有可执行权限的文件。该权限由操作系统检测。<br />
&#8216;<span>-F</span>&#8216;(对子请求存在的文件)<br />
检查TestString是否为一个有效的文件，而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查，由于会降低服务器的性能，所以请谨慎使用！<br />
&#8216;<span>-U</span>&#8216;(对子请求存在的URL)<br />
检查TestString是否为一个有效的URL，而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查，由于会降低服务器的性能，所以请谨慎使用！</p></blockquote>
<p>注意：所有这些测试都可以用惊叹号作前缀(&#8216;!&#8217;)以实现测试条件的反转。<br />
3、还可以在CondPattern之后追加特殊的标记<span>[flags]</span>作为RewriteCond指令的第三个参数。flags是一个以逗号分隔的以下标记的列表：</p>
<blockquote><p>&#8216;<span>nocase|NC</span>&#8216;(忽略大小写)<br />
它使测试忽略大小写，扩展后的TestString和CondPattern中&#8217;A-Z&#8217; 和&#8217;a-z&#8217;是没有区别的。此标记仅用于TestString和CondPattern的比较，而对文件系统和子请求的检查不起作用。<br />
&#8216;<span>ornext|OR</span>&#8216;(或下一条件)<br />
它以OR方式组合若干规则的条件，而不是隐含的AND。典型的例子如下：</p>
<p>RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]<br />
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]<br />
RewriteCond %{REMOTE_HOST}  ^host3.*<br />
RewriteRule &#8230; 针对这3个主机的规则集 &#8230;如果不用这个标记，你就必须要书写三次条件/规则对。</p></blockquote>
<p><span>举例</span><br />
如果要按请求头中的&#8221;User-Agent:&#8221;重写一个站点的主页，可以这样写：</p>
<pre>RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]</pre>
<p>解释：如果你使用的浏览器识别标志是&#8217;Mozilla&#8217;，则你将得到内容最大化的主页(含有Frames等等)。如果你使用的是(基于终端的)Lynx， 则你得到的是内容最小化的主页(不含table等等)。如果上述条件都不满足(使用的是其他浏览器)，则你得到的是一个标准的主页。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/10/19/2318/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/10/19/2318/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/10/19/2318/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/10/19/2318/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/10/19/2318/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/server/apache/" title="Apache" rel="tag nofollow">Apache</a>, <a href="http://www.iwanna.cn/tags/apache/" title="Apache" rel="tag nofollow">Apache</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/10/09/2276/" title="深入理解Apache的mod_rewrite (2009年10月9日)">深入理解Apache的mod_rewrite</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/10/19/2321/" title="Apache中 RewriteRule 规则参数介绍 (2009年10月19日)">Apache中 RewriteRule 规则参数介绍</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/10/19/2318/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入理解Apache的mod_rewrite</title>
		<link>http://www.iwanna.cn/archives/2009/10/09/2276/</link>
		<comments>http://www.iwanna.cn/archives/2009/10/09/2276/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 05:16:42 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=2276</guid>
		<description><![CDATA[人们一提到.htaccess配置文件，首先映入他们脑海的就是用mod_rewrite进行URL地址重定向。对mod_rewrite的看法各不相同，为了就人们对mod_rewrite是怎么认识的有一个快速的看法，我在twitter上搜索了一下&#8221;mod_rewrite&#8221;，并且将我写这篇文章时的前几个搜索页面的结果找出来：

midk：啊！.hatccess和mod_rewrite是如此的痛苦……
basterzenbach:我喜欢mod_rewrite。在我的有生之年，我都可以用它工作，并且还是不能精通它——太强大了。
mikemackay:仍然喜欢mod_rewrite的灵活性——又得到了拯救。这往往容易被忽略……并且要比你想想的要简单！
hostpc:我讨厌mod_rewrite。无法用它正常工作。
awanderingmind:噢，Wordpress 和Apache，你们带给了我烦恼。该死的mod_rewrite！
danielishiding:为什么mod_rewrite不工作了！该死！
我注意到人们清楚的认识到了mod_rewrite的强大，但是往往在语法面前望而却步。考虑到Apache的mod_rewrite文档在前面几页说了同样的问题，这并不奇怪：
“mod_rewrite例子和文档的数量，尽管可以以吨来计算，但是它是巫术。该死的冷漠的巫术，但仍然是巫术。“——-布莱恩摩尔
太糟糕了！因此，在本文中。我真的试图使mod_rewrite的难度降低一个档次。我不仅要去尝试解决mod_rewrite的的语法，还要设法提供一个工作流程，使你可以通过它调试和解决你的mod_rewrite问题。我也会给你一些有用的现实世界中的例子。
然 而，在开始之前，我还要做一个警告。许多学科，尤其是这个，除非你自己动手尝试，否则你是不会学会的！这就是为何我会更专注于教授一个调试工作流程。像往 常一样，如果你还没有加载模块，我会告诉你如何安装好你的系统。我敦促你们在你们自己服务器上做这些例子，如果是测试环境，则更好。你的经验和成功次数越 多，你就会越容易将这种知识扩展到更高级的例子和应用。享受吧。
mod_rewrite的是什么？

mod_rewrite的 是一个Apache模块，可使服务器操纵请求的网址。根据一系列规则对传入的网址进行检查，规则中包含一个正则表达式来检测特定的格式。 如果在地址中发现了一个格式，并且满足适当的条件，该格式就会被一个替代的字符串或者是动作取代。这一过程一直在进行着，直到没有更多的规则或是程序被明 确告诉停止。
上面的内容可以总结为以下3点：
*有一个按顺序排列的处理规则列表。
*如果有一个规则相匹配，它会检查那条规则满足的条件。
*如果一切都匹配，它会替代或这是做出一个动作。
mod_rewrite的优点
用这样的一个地址重定向工具有很明显的优点，但是有一些东西也不是很明显。
人们用mod_rewrite的 主要原因是为了将丑陋的、神秘的网址转化为所谓的“友好的地址”或者是“干净的地址”。新网址通过多种方式变的友好，而不是仅仅一种。 它们是用户友好的，表现在可更容易为人类所理解，瞥一眼就可以，并且用户可能自己来操纵网址。作为额外的奖励，这些网址对搜索引擎来说也是友好的。创建友 好的网址是一个搜索引擎优化技术，网址是一种有效描述他链接的内容的方式。看看下面的例子：

不是很友好: http://example.com/user.php?id=4512 
比较友好: http://example.com/user/4512/ 
甚至更好:     http://example.com/user/Joe/ 

最后的链接不仅仅是看上去变的简单了，它还可以使搜索引擎从中提取语义。这种基本的URL重写机制是使用mod_rewrite的一种方式。然而，正如你将要看到的一样，除了这些简单的转换，它还可以作很多的事情。
将同一个例子扩展一下，一些人声称通过用mod_rewrite改变你的网址可以获得安全效益。给出同一个例子，想像，考虑一下下面这个对用户id的攻击：


http://example.com/user.php?id=AHHHHHH 
http://example.com/user/AHHHHHH/



 第一个例子是明确的PHP脚本调用，并且必须得处理无效的ID号。写得不好的脚本可能会失败，更极端的情况是（写得不好的Web应用程序）错误的输入可 能导致数据损坏。然而，如果只给用户显示友好的网址，也就是说他们甚至不知道user.php网页的存在，他们可能只知道友好的URL结构。试图在这种情 况下进行的攻击可能在读取PHP脚本之前就已经失败了。这是因为mod_rewrite的核心是正则表达式的格式匹配。在上面的例子中，你的地址中可能有一个数字，比如（\ d +），而不是字符，像a-z，当重写模块找到的是字母而不是数字时，重写就会失败。

从安全的角度讲，这种额外的抽象功能是不错的。如果你愿意，你甚至可以防止直接访问原始PHP脚。不过，我们决不能使用mod_rewrite来替换一般的安全措施，你的脚本应当在服务器端进行验证。
在服务器上启用mod_rewrite模块
就像启用.htaccess支持一样，启用mod_rewrite或者是其他apache模块必须修改全局配置文件（httpd.conf）。就像前面说的一样，由于mod_rewrite用的是如此广泛，主机提供商几乎总是启用这个模块的。然而，如果你怀疑你的主机提供商没有启用它（我们会在下面测试），你应当联系他们，并且他们很乐意启用它。
如果你是自己安装的Apache，毫无疑问，当编译Apache的时候，要将Mod_rewrite模块包括进来，因为默认情况下是不包括它的。然而，它是用的如此普遍，几乎所有的安装指南，包括Apache的安装文档都会在他们的示例中指出如何将它编译进来。然而，预先包装的版本已经将它启用了。如果你正在读这篇文章，那么你的Apache有99%的可能已经将mod_rewrite模块编译进来了，所以你只须进入下一个步骤。

如果你是你们网络的网络管理员，并且你想确认一下你已经加载了这个模块，你应当检查一下httpd.conf文件。在配置文件有很大一部分用于加载那一 大堆模块。下面的行可能会出现在文件中，如果是，好极了！如果它被注释掉了，或者说是在它前面有一个#号，哪么你只需将#号删除掉，留下下面的这一部分：

1、LoadModule rewrite_module modules/mod\_rewrite.so
老版本的Apache1.3，可能需要你在LoadModule目录中加上以下目录：



# Only in Apache 1.3 
AddModule mod\_rewrite.c 


然而，这好像在Apache 2及以后的版本中消失了，只需要LoadModule指令。
如果你不得不修改配置文件，那么你必须重启你的apache服务。你要记住备份你的原始文件，以防万一你需要将它还原回以前的版本。
测试mod_rewrite模块
你可以通过多种方式测试mod_rewrite模块是否启用（或者是工作）了，最简单的方法是查看PHP的phpinfo函数的输出。创建下面的这个非常简单的PHP页面，在你的浏览器中打开它，并且在输出结果中找一下&#8221;mod_rewrite&#8221;。
&#60;?php phpinfo(); ?&#62;
mod_rewrite应该会显示在网页的“Loaded Modules”部分中，就像这样：

然而，如果你用的不是PHP（虽然在接下来的教程中我会用它），还有很多方式来测试。Apache有许多命令行工具。
在我的基本身份验证的第一个教程中，我提到了在htpasswd的工具。你可以使用诸如apachectl或者httpd的其他工具直接对模块进行测试。有命令行开关可以使你检查现有的已经安装加载的模块。您可以执行下面的命令来得到一个所有已加载的模块的列表。
shell&#62; apachectl -t -D DUMP_MODULES 
这里我展示的是这个命令的帮组页面。然后，我运行了这个命令，并在结果中查找了“rewrite”，有一行输出与之相匹配。

最后，如果你还是不能确定它是否启用了，像以前一样将它注释掉，看看会发生什么！之后，我会介绍语法，但这里仅仅是一个测试，看看他是否工作了。下面的.htaccess文件将重定向任何给定的文件夹请求到good.html文件，这意味着如果你的mod_rewrite工作了，你应该看到good.html。如果mod_rewrite不工作，那么你会看到一个带警告的index.html。


# Redirect everything in this directory to &#8220;good.html&#8221; 
RewriteEngine on [...]]]></description>
			<content:encoded><![CDATA[<p>人们一提到.htaccess配置文件，首先映入他们脑海的就是用mod_rewrite进行URL地址重定向。对mod_rewrite的看法各不相同，为了就人们对mod_rewrite是怎么认识的有一个快速的看法，我在twitter上搜索了一下&#8221;mod_rewrite&#8221;，并且将我写这篇文章时的前几个搜索页面的结果找出来：<br />
<span id="more-2276"></span></p>
<p style="padding-left: 30px;">midk：啊！.hatccess和mod_rewrite是如此的痛苦……</p>
<p style="padding-left: 30px;">basterzenbach:我喜欢mod_rewrite。在我的有生之年，我都可以用它工作，并且还是不能精通它——太强大了。</p>
<p style="padding-left: 30px;">mikemackay:仍然喜欢mod_rewrite的灵活性——又得到了拯救。这往往容易被忽略……并且要比你想想的要简单！</p>
<p style="padding-left: 30px;">hostpc:我讨厌mod_rewrite。无法用它正常工作。</p>
<p style="padding-left: 30px;">awanderingmind:噢，Wordpress 和<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>，你们带给了我烦恼。该死的mod_rewrite！</p>
<p style="padding-left: 30px;">danielishiding:为什么mod_rewrite不工作了！该死！</p>
<p>我注意到人们清楚的认识到了mod_rewrite的强大，但是往往在语法面前望而却步。考虑到<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的mod_rewrite文档在前面几页说了同样的问题，这并不奇怪：</p>
<p style="padding-left: 30px;">“mod_rewrite例子和文档的数量，尽管可以以吨来计算，但是它是巫术。该死的冷漠的巫术，但仍然是巫术。“——-布莱恩摩尔</p>
<p>太糟糕了！因此，在本文中。我真的试图使mod_rewrite的难度降低一个档次。我不仅要去尝试解决mod_rewrite的的语法，还要设法提供一个工作流程，使你可以通过它调试和解决你的mod_rewrite问题。我也会给你一些有用的现实世界中的例子。</p>
<p>然 而，在开始之前，我还要做一个警告。许多学科，尤其是这个，除非你自己动手尝试，否则你是不会学会的！这就是为何我会更专注于教授一个调试工作流程。像往 常一样，如果你还没有加载模块，我会告诉你如何安装好你的系统。我敦促你们在你们自己服务器上做这些例子，如果是测试环境，则更好。你的经验和成功次数越 多，你就会越容易将这种知识扩展到更高级的例子和应用。享受吧。</p>
<p><strong><span style="font-size: medium;">mod_rewrite的是什么？<br />
</span></strong><br />
mod_rewrite的 是一个<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>模块，可使服务器操纵请求的网址。根据一系列规则对传入的网址进行检查，规则中包含一个正则表达式来检测特定的格式。 如果在地址中发现了一个格式，并且满足适当的条件，该格式就会被一个替代的字符串或者是动作取代。这一过程一直在进行着，直到没有更多的规则或是程序被明 确告诉停止。</p>
<p>上面的内容可以总结为以下3点：</p>
<p>*有一个按顺序排列的处理规则列表。<br />
*如果有一个规则相匹配，它会检查那条规则满足的条件。<br />
*如果一切都匹配，它会替代或这是做出一个动作。</p>
<p><strong><span style="font-size: medium;">mod_rewrite的优点</span></strong></p>
<p>用这样的一个地址重定向工具有很明显的优点，但是有一些东西也不是很明显。</p>
<p>人们用mod_rewrite的 主要原因是为了将丑陋的、神秘的网址转化为所谓的“友好的地址”或者是“干净的地址”。新网址通过多种方式变的友好，而不是仅仅一种。 它们是用户友好的，表现在可更容易为人类所理解，瞥一眼就可以，并且用户可能自己来操纵网址。作为额外的奖励，这些网址对搜索引擎来说也是友好的。创建友 好的网址是一个搜索引擎优化技术，网址是一种有效描述他链接的内容的方式。看看下面的例子：</p>
<ol>
<li><span><span>不是很友好: http://example.com/user.php?</span><span>id</span><span>=</span><span>4512</span><span> </span></span></li>
<li><span>比较友好: http://example.com/user/4512/ </span></li>
<li><span>甚至更好:     http://example.com/user/Joe/ </span></li>
</ol>
<div dir="ltr">最后的链接不仅仅是看上去变的简单了，它还可以使搜索引擎从中提取语义。这种基本的URL重写机制是使用mod_rewrite的一种方式。然而，正如你将要看到的一样，除了这些简单的转换，它还可以作很多的事情。</p>
<p>将同一个例子扩展一下，一些人声称通过用mod_rewrite改变你的网址可以获得安全效益。给出同一个例子，想像，考虑一下下面这个对用户id的攻击：</p></div>
<div dir="ltr">
<ol>
<li><span><span>http://example.com/user.php?</span><span>id</span><span>=</span><span>AHHHHHH</span><span> </span></span></li>
<li><span>http://example.com/user/AHHHHHH/<br />
</span></li>
</ol>
</div>
<div dir="ltr"><span> 第一个例子是明确的PHP脚本调用，并且必须得处理无效的ID号。写得不好的脚本可能会失败，更极端的情况是（写得不好的<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">Web</a>应用程序）错误的输入可 能导致数据损坏。然而，如果只给用户显示友好的网址，也就是说他们甚至不知道user.php网页的存在，他们可能只知道友好的URL结构。试图在这种情 况下进行的攻击可能在读取PHP脚本之前就已经失败了。这是因为mod_rewrite的核心是正则表达式的格式匹配。在上面的例子中，你的地址中可能有一个数字，比如（\ d +），而不是字符，像a-z，当重写模块找到的是字母而不是数字时，重写就会失败。</span></div>
<div dir="ltr"><span><br />
从安全的角度讲，这种额外的抽象功能是不错的。如果你愿意，你甚至可以防止直接访问原始PHP脚。不过，我们决不能使用mod_rewrite来替换一般的安全措施，你的脚本应当在服务器端进行验证。</span></div>
<div dir="ltr"><strong><span style="font-size: medium;">在服务器上启用mod_rewrite模块</span></strong></div>
<div dir="ltr">就像启用.htaccess支持一样，启用mod_rewrite或者是其他<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">apache</a>模块必须修改全局配置文件（httpd.conf）。就像前面说的一样，由于mod_rewrite用的是如此广泛，主机提供商几乎总是启用这个模块的。然而，如果你怀疑你的主机提供商没有启用它（我们会在下面测试），你应当联系他们，并且他们很乐意启用它。</div>
<div dir="ltr">如果你是自己安装的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>，毫无疑问，当编译<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的时候，要将Mod_rewrite模块包括进来，因为默认情况下是不包括它的。然而，它是用的如此普遍，几乎所有的安装指南，包括<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的安装文档都会在他们的示例中指出如何将它编译进来。然而，预先包装的版本已经将它启用了。如果你正在读这篇文章，那么你的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>有99%的可能已经将mod_rewrite模块编译进来了，所以你只须进入下一个步骤。</div>
<div dir="ltr">
如果你是你们网络的网络管理员，并且你想确认一下你已经加载了这个模块，你应当检查一下httpd.conf文件。在配置文件有很大一部分用于加载那一 大堆模块。下面的行可能会出现在文件中，如果是，好极了！如果它被注释掉了，或者说是在它前面有一个#号，哪么你只需将#号删除掉，留下下面的这一部分：</div>
<div dir="ltr">
<p style="padding-left: 30px;">1、LoadModule rewrite_module modules/mod\_rewrite.so</p>
<div>老版本的Apache1.3，可能需要你在LoadModule目录中加上以下目录：</div>
</div>
<div>
<ol>
<li><span><span># Only in <a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a> 1.3 </span></span></li>
<li><span>AddModule mod\_rewrite.c </span></li>
</ol>
</div>
<div>然而，这好像在<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a> 2及以后的版本中消失了，只需要LoadModule指令。</div>
<div>如果你不得不修改配置文件，那么你必须重启你的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">apache</a>服务。你要记住备份你的原始文件，以防万一你需要将它还原回以前的版本。</div>
<div><strong><span style="font-size: medium;">测试mod_rewrite模块</span></strong></div>
<div>你可以通过多种方式测试mod_rewrite模块是否启用（或者是工作）了，最简单的方法是查看PHP的phpinfo函数的输出。创建下面的这个非常简单的PHP页面，在你的浏览器中打开它，并且在输出结果中找一下&#8221;mod_rewrite&#8221;。</div>
<div style="padding-left: 30px;">&lt;?php phpinfo(); ?&gt;</div>
<div>mod_rewrite应该会显示在网页的“Loaded Modules”部分中，就像这样：</div>
<div><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/phpinfo.png" alt="" width="643" height="431" /></div>
<div>然而，如果你用的不是PHP（虽然在接下来的教程中我会用它），还有很多方式来测试。<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>有许多命令行工具。</div>
<div dir="ltr">在我的基本身份验证的第一个教程中，我提到了在htpasswd的工具。你可以使用诸如apachectl或者httpd的其他工具直接对模块进行测试。有命令行开关可以使你检查现有的已经安装加载的模块。您可以执行下面的命令来得到一个所有已加载的模块的列表。</div>
<div style="padding-left: 30px;" dir="ltr"><span>shell</span><span>&gt;</span><span> apachectl -t -D DUMP_MODULES </span></div>
<div dir="ltr">这里我展示的是这个命令的帮组页面。然后，我运行了这个命令，并在结果中查找了“rewrite”，有一行输出与之相匹配。</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/apachectl.png" alt="" width="742" height="542" /></div>
<div dir="ltr">最后，如果你还是不能确定它是否启用了，像以前一样将它注释掉，看看会发生什么！之后，我会介绍语法，但这里仅仅是一个测试，看看他是否工作了。下面的.htaccess文件将重定向任何给定的文件夹请求到good.html文件，这意味着如果你的mod_rewrite工作了，你应该看到good.html。如果mod_rewrite不工作，那么你会看到一个带警告的index.html。</div>
<div dir="ltr">
<ol>
<li><span><span># Redirect everything in this directory to &#8220;good.html&#8221; </span></span></li>
<li><span>RewriteEngine on </span></li>
<li><span>RewriteRule .* good.html </span></li>
</ol>
</div>
<div dir="ltr">下面是正确的和错误的页面：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/bare_good.png" alt="" width="462" height="322" /></div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/bare_bad.png" alt="" width="504" height="363" /></div>
<div dir="ltr"><strong><span style="font-size: medium;">.htaccess的内容</span></strong></div>
<div dir="ltr">通常情况下，你可以写在.htaccess文件中的内容也可以写到全局配置文档中。在mod_rewrite中，如果你将一条规则放的文件不同，会有一点儿小差异。最明显的是：</div>
<div style="padding-left: 30px;" dir="ltr">如果你将【……】规则放到了.htaccess文件中，目录的前缀（/)在REQUEST_URI变量中会被去掉，因为所有的请求会被自动假设是现在目录的相对地址。——<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>文档</div>
<div dir="ltr">有一点要记住，如果你在网上看例子或者是你自己在测试一个实例，要注意前面的斜线！当我将一些例子放到一起的时候，我将在下面试图澄清这些问题。</div>
<div dir="ltr"><strong><span style="font-size: medium;">正则表达式</span></strong></div>
<div dir="ltr">本教程不打算教你正则表达式。对于那些你知道的正则表达式，mod_rewrite中 用到的正则表达式会根据<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>版本的不同而有所改变。在<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a> 2.0中，他们似乎是与Perl兼容（pcre）的正则表达式。这意味着许多你所使用的简写，例如\w的意思是[A-Za-z0-9]，\d的意思是 [0-9]，以及更多不存在的简写。但是，我的公司使用的是<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a> 1.3，并且Apache1.3的正则表达式是比较有限的。</div>
<div dir="ltr">如果你不知道正则表达式，下面这些有用的教程会让你快速入门：</div>
<div dir="ltr">
<ul>
<li><a href="http://blog.themeforest.net/screencasts/a-crash-course-in-regular-expressions/">Nettuts very own Jeffrey’s Crash Course</a></li>
<li><a href="http://immike.net/blog/2007/04/06/the-absolute-bare-minimum-every-programmer-should-know-about-regular-expressions/">The Absolute Bare Minimum Every Programmer Should Know About Regular Expressions</a></li>
<li><a href="http://en.kerouac3001.com/regex-tutorial-8.htm">Quick And Practical Tutorial</a></li>
<li><a href="http://www.smashingmagazine.com/2009/05/06/introduction-to-advanced-regular-expressions/">Smashing Magazine Links on Regular Expressions</a></li>
</ul>
</div>
<div dir="ltr">还有每个人都应该知道的一些引用：</div>
<div dir="ltr">
<ul>
<li><a href="http://www.addedbytes.com/download/regular-expressions-cheat-sheet-v2/png">Popular Added Bytes Cheatsheet For Regular Expressions</a></li>
<li><a href="http://www.addedbytes.com/apache/mod_rewrite-cheat-sheet/">Added Bytes Cheatsheet for mod_rewrite</a></li>
<li><a href="http://rick.measham.id.au/paste/explain.pl?regex=%5Cd%2B%28.%5Cd%2B%29%3F%28%5BeE%5D%5Cd%2B%29%3F">Explain Regular Expressions</a></li>
</ul>
<div dir="ltr">如果有还没有花时间去学习正则表达式，我强烈建议你花点时间学习一下。因为通常情况下，他们没有你想象的那么复杂。我从多年的经验中选择了上面的那些关于正则表达式的链接，我觉得这些指南对于学习最基础的东西来说，写的很好。如果你想有效的利用mod_rewrite，正则表达式是至关重要的，在其他方面，了解他们也很有用，如在你最喜爱的代码编辑器中使用“查找/替换”。</div>
</div>
<div dir="ltr"><strong><span style="font-size: medium;">初次体验</span></strong></div>
<div dir="ltr">好了，你等待的耐心已经足够大了，让我们快速的看一个例子。这个例子在链接的源代码中有。这里只给出.htaccess文件的代码：</div>
<div dir="ltr">
<ol>
<li><span><span># Enable Rewriting </span></span></li>
<li><span>RewriteEngine on </span></li>
<li><span> </span></li>
<li><span># Rewrite user URLs </span></li>
<li><span>#   Input:  user/NAME/ </span></li>
<li><span>#   Output: user.php?<span>id</span><span>=</span><span>NAME</span><span> </span></span></li>
<li><span>RewriteRule ^user/(\w+)/?$ user.php?<span>id</span><span>=$1<br />
</span></span></li>
</ol>
</div>
<div dir="ltr"><span><span> 在我对它做任何解释之前，我会先讲解一下目录中的另外一个文件。</span></span></div>
<div dir="ltr">目录中包含两个文件：index.php和user.php。index.php中有一些指向user页面的链接或者是各种各样的格式。php代码用来显示页面被请求了，并检查传过来的&#8221;id&#8221;参数。下面是user.php的代码：</div>
<div dir="ltr">
<ol>
<li><span><span>&lt;?php </span></span></li>
<li><span> </span></li>
<li><span><span>// Get the username from the url</span><span> </span></span></li>
<li><span><span>$id</span><span> = </span><span>$_GET</span><span>[</span><span>'id'</span><span>]; </span></span></li>
<li><span> </span></li>
<li><span>?&gt;&lt;!DOCTYPE html PUBLIC <span>&#8220;-//W3C//DTD XHTML 1.0 Strict//EN&#8221;</span><span> </span></span></li>
<li><span> <span>&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&#8221;</span><span>&gt; </span></span></li>
<li><span>&lt;html xmlns=<span>&#8220;http://www.w3.org/1999/xhtml&#8221;</span><span> xml:lang=</span><span>&#8220;en&#8221;</span><span> lang=</span><span>&#8220;en&#8221;</span><span>&gt; </span></span></li>
<li><span>&lt;head&gt; </span></li>
<li><span> &lt;meta http-equiv=<span>&#8220;Content-Type&#8221;</span><span> content=</span><span>&#8220;text/html; charset=utf-8&#8243;</span><span>/&gt; </span></span></li>
<li><span> &lt;title&gt;Simple mod\_rewrite example&lt;/title&gt; </span></li>
<li><span> &lt;style type=<span>&#8220;text/css&#8221;</span><span>&gt; .green { color: green; } &lt;/style&gt; </span></span></li>
<li><span>&lt;/head&gt; </span></li>
<li><span>&lt;body&gt; </span></li>
<li><span> &lt;h1&gt;You Are on user.php!&lt;/h1&gt; </span></li>
<li><span> &lt;p&gt;Welcome: &lt;span <span>class</span><span>=</span><span>&#8220;green&#8221;</span><span>&gt;&lt;?php </span><span>echo</span><span> </span><span>$id</span><span>; ?&gt;&lt;/span&gt;&lt;/p&gt; </span></span></li>
<li><span>&lt;/body&gt; </span></li>
<li><span>&lt;/html&gt;<br />
</span></li>
</ol>
</div>
<div dir="ltr"><span> 这个例子有一些不同的地方。首先，</span>请注意URL重写必须通过 RewriteEngine指令启用！如果你的htaccess文件要使用重写规则，应始终包括这行，否则你不能确定它是否启用了！作为一个经验法则，总 是将它包括进去并确保每个.htaccess文件中你只包含了一个。字符串“on”不区分大小写，因此，当你在网上看到其他的例子用的是“On”，这是可 以接受的。</div>
<div dir="ltr">第一个重写规则是用来处理user.php页面的。就像这些注释说的一样，我们正在将友好的网址重写为正常的URL格式。为了做到这一点，当输入友好的网址时，事实上，我们将它转化成了标准的查询字符串URL。将它分解开，我们就得到了：</div>
<div dir="ltr">
<ol>
<li><span><span>T规则: </span></span></li>
<li><span>RewriteRule ^user/(\w+)/?$ user.php?<span>id</span><span>=$1 </span></span></li>
<li><span> </span></li>
<li><span>匹配模式: </span></li>
<li><span>^             输入的开头</span></li>
<li><span>user/          以“user/“开始的请求地址 </span></li>
<li><span>(\w+)        提取所有的字母，并将提取的结果传给$1 </span></li>
<li><span>/?             可选的斜线 &#8220;/&#8221; </span></li>
<li><span>$              输入结束 </span></li>
<li><span> </span></li>
<li><span>替换为: </span></li>
<li><span>user.php?<span>id</span><span>=   要用到的字符串</span><span>. </span></span></li>
<li><span>$1             上面第一个提取到的字符串。<br />
</span></li>
</ol>
</div>
<div dir="ltr"><span> 下面是一些例子及对上面每行话的解释：</span></div>
<div dir="ltr">
<table border="0">
<caption>User.php</caption>
<thead>
<tr>
<th>输入</th>
<th>匹配</th>
<th>提取</th>
<th>输出</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>user.php?id=joe</td>
<td>No</td>
<td></td>
<td>user.php?id=joe</td>
<td>Normal</td>
</tr>
<tr>
<td>user/joe</td>
<td>Yes</td>
<td>joe</td>
<td>user.php?id=joe</td>
<td>Good</td>
</tr>
<tr>
<td>user/joe/</td>
<td>Yes</td>
<td>joe</td>
<td>user.php?id=joe</td>
<td>Good</td>
</tr>
<tr>
<td>user/joe/x</td>
<td>No</td>
<td></td>
<td>user/joe/x</td>
<td>Fail</td>
</tr>
</tbody>
</table>
</div>
<div dir="ltr">
<table border="0">
<tbody>
<tr valign="top">
<td>
<div dir="ltr">因此，第一个例子不会受到重写规则的影响，并且可以正常访问。第二个和第三个例子与重写规则相匹配，会根据重写规则被改写，可以正常访问，最后一个例子 不符合规则且无法访问。服务器没有用户目录，不能试图找到它。这是预期的结果，因为user/joe/ x是一个无法访问的网址！</div>
</td>
</tr>
<tr>
<td>这个例子比较容易理解。然而，为了澄清任何更复杂的事情，就像我现在做的一样，我必须要花好几分钟去注意细节。在下一节中，我们将举一个更复杂的例子，这个例子涉及所有重写的核心内容。</td>
</tr>
</tbody>
</table>
</div>
<div dir="ltr">注意：如果这个例子不能在你的机器上运行，可能是由于你的<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>或mod_rewrite 版本与PCRE不兼容。请尝试着将^user/(\w+)/?$改为 <code>^user/([a-z]+)/?$。 请注意，我没有使用\w的缩写。如果此版本可以在你的机器上正确运行，那么你不要使用正则表达式的缩写，要使用较长的当量（见上面的正则表达式节）。</code></div>
<div dir="ltr"><strong><span style="font-size: medium;">执行流程详情</span></strong></div>
<div dir="ltr">重写规则的执行流程比较简单，但不是完全明了。因此，我将叙述一下细节。这一切都开始于用于向你的服务器提出请求的时候。他们在浏览器地址栏中键入网址， 他们的浏览器将之转换成一个HTTP请求并发送到服务器，<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>收到这一请求，并将之解析成片断。下面是一个例子：</div>
<p><!--more--></p>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/url_full.png" alt="" width="482" height="440" /></div>
<div dir="ltr"><span style="color: #999999;"><br />
</span></div>
<div dir="ltr">
<table border="0">
<tbody>
<tr valign="top">
<td>
<div dir="ltr"><span style="color: #999999;"> 请注意，每当我提到<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的变量，我使用了一种奇怪的语法：％｛APACHE_VAR｝。这是因为它类似于mod_rewrite访问变量的语法。不过，括号内名字是重要的。</span></div>
</td>
</tr>
<tr>
<td>
<table border="0">
<tbody>
<tr valign="top">
<td>
<div dir="ltr">那么，mod_rewrites是如何工作的？如果你用的是.htaccess文件，那么你只需输入REMOTE_URI部分，但没有开始的斜线！我之前提到过这个，对大多数刚刚开始用它的人来说，这显得很混乱。如果你是将它添加到了全局配置文件里，那么你应当加上斜线。</div>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<div dir="ltr">为了说的更具体一点儿，下面是<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的文档中对mod_rewrite中“URL部分”的描述：</div>
<div style="padding-left: 30px;" dir="ltr">
<table border="0">
<tbody>
<tr valign="top">
<td>
<div dir="ltr">该模式始终是对请求的URL路径进行正则表达式匹配（主机名后面的那部分，但在任何以问号为标志的显示查询字符串的前面）。 <a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>文档</div>
</td>
</tr>
</tbody>
</table>
</div>
<div dir="ltr">为了消除大家的模糊不清的认识，下面用黄色高亮显示的两个网址是mod_rewrite在.htaccess文件中的“部分网址”：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/url_part.png" alt="" width="486" height="422" /></div>
<div dir="ltr">在本节接下来的部分我将利用这两个网址来描述执行的流程。我将把第一个网址称为“绿色”网址，第二个称为“蓝色”网址。在整个分析中，我还将使用“URL部分”来表示开始处没有斜线的REMOTE_URI。</div>
<div dir="ltr">
对于那些想要100％的区分开这两中教法的人，我这里说的URL其实是URI。一个统一资源标识符（URI）的定义有别于统一资源定位符（URL）。一个 URI只是标识资源在哪里，这意味着存在多个URl可以指向相同的资源，但是他们是不同的地址。一个URI可能在找到资源之前经过了数次跳动和重定向。然 而，URL却是标识资源的确切位置。这种细微的差别随着时间的推移，变得越来月模糊，以至于没有人关心它们的差异。我将继续使用术语URL，因为人们用它 更舒服一些。</div>
<div dir="ltr">
所以，现在我们知道重写规则将要采取行动了。一旦<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>已解析出请求，它就会将它翻译成它认为的文件，并去读取该文件。在这个过程中，他会搜 索.htaccess文件。假设，.htaccess文件起用了RewriteEngine，那么任何重写规则都可以更改网址。地址的急剧变化（如 <a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>将某个网址原来指向的目录替换为另外一个目录）将促发<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>发出子请求，进而获取新的文件。</div>
<div dir="ltr">
在大多数情况下，你是可以看到子请求的。这些实现细节对于了解你写的或使用的大多数简单的重写规则来说并不重要。更重要的是知道<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>如何处理.htaccess文件中的重写规则。</div>
<div dir="ltr">
.htaccess文件中的规则会以它们出现的顺序被处理。请注意，每个重写规则都是“部分网址”，也就是说类似于REMOTE_URI。当一个规则促 发替换的时候，修改后的“部分网址”将被移交给下一个规则。这意味着，正在处理的网址可能已经被前面的规则修改过了，网址会被每个相匹配的规则更新。这一 点很重要！</div>
<div dir="ltr">
下面是一个流程图，它试图提供URL在通过含有多个规则的.htaccess文件时的执行过程：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/flow_chart.png" alt="" /></div>
<div dir="ltr">请注意，流程图的顶部的将会与重写规则进行匹配的数据是“网址部分”，如果替换成功，则修改过的网址会与下一条规则继续匹配。</div>
<div dir="ltr">
前面，我介绍了重写条件，但是没有详谈。每个重写过程都与一条重写规则相关联。条件出现在与它们有联系的规则之前，但是只有与规则相匹配了，网址才会得 到评估。正如流程图所示，如果与一个重写规则相匹配了，<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>会检查这条规则有什么条件（即做出替换是否需要其他条件）。如果没有条件，那么将进行 替代并进入下一步。如果需要条件，那么只有所有的条件都成立的时候，才会进行替换。举一个具体的例子。</div>
<div dir="ltr">
我用的网址实际上是我放在&#8221;profile_example&#8221;目录中的源代码的一部分。这和前面的例子user.php一样，但现在有一个profile.php页面，一个附加的重写规则，和一个条件！让我们看一下这段代码和它在<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>中的执行过程：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/profile_rules.png" alt="" /></div>
<div dir="ltr">这里有两个规则。规则＃1和我们前面看到的user例子一样。规则＃2是新加的，注意它有一个条件。在“网址部分”我们已经讨论过会从上到下遍历每一条规则。因此，必须先经过规则＃1，然后才是规则＃2。</div>
<div dir="ltr">
理解这个例子的关键是首先要了解目标。在这个例子中，我允许友好网址，但实际上，我要明确地禁止直接访问PHP页面。请注意，有些人可能会说这是一个坏主 意。他们可能会说，作为开发者，这个调试起来会更难。是这样的，事实上我不推荐做这样的小把戏，但是作为一个例子，这很好。更实际的使用mod_rewrite的例子会在本教程后面的部分看到。</div>
<div dir="ltr">
因此，在这一点的基础上，让我们看看我绿色网址发生了什么。这次，我们希望取得成功。</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/green_flow.png" alt="" width="525" height="746" /></div>
<div dir="ltr">在最上面，可以看到<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的THE_REQUEST变量。我把它放在上方是因为它不像我们要处理的其他<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>变量，在请求期间这个变量的值 不会改变。这就是规则＃2使用％｛THE_REQUEST｝的原因之一。在THE_REQUEST下面，我们看到绿色的“网址部分”开始进入第一个规则 了：</div>
<div dir="ltr">
<ul>
<li>URL匹配成功。</li>
<li>没有任何条件，因此继续。</li>
<li>进行替换。</li>
<li>没有任何标志，因而继续。</li>
</ul>
</div>
<div dir="ltr">通过第一条规则后，该网址已经更改。网址已被重写成了profile.php?id=joe，这时，<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>会听下来更新它的大多数变量。我们看不到?id=joe，新的“网址部分”会进入下一条规则。这是我们第一次遇到条件：</div>
<div dir="ltr">
<ul>
<li>URL匹配成功。</li>
<li>还有条件，我们将检查条件。</li>
<li>THE_REQUEST不包含profile.php，因此条件检查失败。</li>
<li>因为不满足条件，所以我们忽略替换和标志。</li>
<li>这条规则没有改变URL。</li>
</ul>
</div>
<div dir="ltr">这一次，我们通过了所有的重写规则，并且<code>profile.php?id=joe</code> 页会被正确的提取。</div>
<div dir="ltr">
下面介绍关于如何执行蓝色的URL，这一次，我们要失败：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/blue_flow.png" alt="" width="532" height="716" /></div>
<div dir="ltr">我再次将THE_REQUEST的值放在了最上面，蓝色的“网址部分”进入规则＃1：</div>
<div dir="ltr">
<ul>
<li>URL匹配失败。</li>
<li>其他的一切都被忽略，网址没有改变，进入下一步。</li>
</ul>
</div>
<div dir="ltr">第一个规则很容易。通常情况下，如果URL匹配失败，那么它会原样进入下一步。现在进入规则＃2：</div>
<div dir="ltr">
<ul>
<li>URL匹配成功。</li>
<li>有条件需要比较，因此会先测试条件。</li>
<li>请求包含 <code>profile.php，因此条件测试通过。</code></li>
<li>通过所有的条件，我们可以替换网址了。</li>
<li>”-”是一个特殊的替换，这一为着任何东西都不会改变了。</li>
<li>规则中有标志，因此我们处理标志。</li>
<li>有一个F标志，意思是返回一个禁止访问响应。</li>
<li><code><span style="font-family: Verdana,Arial,Helvetica,sans-serif;">一个</span></code><code>403 Forbidden响应发送到了客户端。</code></li>
</ul>
</div>
<div dir="ltr">有几件事情值得再重复一次。为了使替换发生，所有条件都必须检查通过。在上面这种情况下只有一个条件，并且检查通过了，所以，可以对网址进行替换。注意， 有一种特殊的替换，不改变任何东西。当你想用标志做点儿什么的时候，这种方法相当有用，在这种情况下，我们就会这样做（指的是，替换后什么都不改变）。</div>
<div dir="ltr">
下面是一个URL例子的分解和它们的返回值表：</div>
<div dir="ltr">
<table border="0">
<caption>Profile.php</caption>
<thead>
<tr>
<th>输入</th>
<th>匹配</th>
<th>获取</th>
<th>输出</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>profile.php?id=joe</td>
<td>Yes (#2)</td>
<td></td>
<td>profile.php?id=joe</td>
<td>Forbidden</td>
</tr>
<tr>
<td>profile/joe</td>
<td>Yes (#1)</td>
<td>joe</td>
<td>profile.php?id=joe</td>
<td>Good</td>
</tr>
<tr>
<td>profile/joe/</td>
<td>Yes (#1)</td>
<td>joe</td>
<td>profile.php?id=joe</td>
<td>Good</td>
</tr>
<tr>
<td>profile/joe/x</td>
<td>No</td>
<td></td>
<td>profile/joe/x</td>
<td>Fail</td>
</tr>
</tbody>
</table>
</div>
<div dir="ltr"><strong><span style="font-size: medium;">语法</span></strong></div>
<div dir="ltr">在介绍重写规则（RewriteRule）和重写条件（RewriteCond）的语法之前，我建议你先下载theAddedBytes Cheatsheet。这是因为cheatsheet表列出了最有用的服务器变量，标志，并有正则表达式技巧，甚至还有几个例子。在那里面有这么多的内 容，将它们关联起来是很难的。</p>
<p>让我们从重写规则开始。如果你想做一些特殊的事，你可以随时查看<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的关于重写规则的文档。下面是我的概述：</p></div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/syntax_rewriterule.png" alt="" /></div>
<div dir="ltr">这个表显示了什么类型的标志是可用的。许多指南涵盖了flags的详细讲解，我会通过通过下面的例子介绍一下我认为的用的最多的flag。</div>
<div dir="ltr">
下面是<a href="http://www.iwanna.cn/tags/apache/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Apache">Apache</a>的RewriteCond文档和我的概述：</div>
<div dir="ltr"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/syntax_rewritecond.png" alt="" /></div>
<div dir="ltr"><strong><span style="font-size: medium;">调试流程</span></strong></div>
<div dir="ltr">当你使用mod_rewrite制定新规则的时候，总是以一个简单的规则开始，并且逐步发展为最后的版本。从来不要试图一下子将所有的事情办好。对于重写条件的编写，这个道理同样适用。一次添加规则和条件，多次测试！</p>
<p>我正在介绍的这种方法的关键之处是它可以让你知道是否你的一个改变不能正常工作或者是使某个地方运行不正常。当一次做得太多的时候，你会不可避免的遇到 错误，并且你将不得不恢复你所做的一切更改来找出问题到底是出在那儿了。这是一项非常艰难的 工作，可能会导致你的失望。不过，如果你总是稳步推进，并且在每一步都可以到达一个可以正常运行的点，你的处境就会稍好一点儿。</p></div>
<div dir="ltr">
人们往往忽略这条建议，创建了一个复杂的规则，最终却不能工作。几个小时后，他们发现问题没有出现在复杂的部分，反而只是简单的正则表达式错误，如果他 们按我上面解释的构造规则的换，问题可能早已经被发现了。在反向工程拆解规则上，这种方法也适用。这种做法将极大降低人们的失望！</div>
<div dir="ltr"><strong><span style="font-size: medium;">例子<br />
</span></strong><br />
在下面的例子中，我总是会假设网站的域名是example.com。此域名很重要，因为它会影响HTTP_HOST变量以及在你的网站上将指定的URL 重定向到另一个文件。如果你打算修改你的任何一个例子，以便它可以在你的网站上工作，请记住这一点。如果是这样，只需用你的域名替换 “example.com”。例如，Nettuts会将“example.com”改为“nettuts.com”。</div>
<div dir="ltr">
<strong><span style="font-size: medium;">删除www<br />
</span></strong><br />
这是最经典的重写规则。这将使得每个通过http://www.example.com访问你网站的人会得到一个硬性的重定向，从而其浏览器的地址栏中也将进行相应更新。</div>
<div dir="ltr">
<ol>
<li><span><span>RewriteEngine on </span></span></li>
<li><span>RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC] </span></li>
<li><span>RewriteRule ^(.*)$ http://example.com/$1 [<span>R</span><span>=</span><span>301</span><span>,L] </span></span></li>
</ol>
</div>
<div dir="ltr">这条规则与任何输入的地址都匹配，并将所有的地址保存为$1。本例中的重要组成部分是条件语句，这个条件会检查HTTP_HOST变量，看它是否以“www”开始。如果是这样，重写就会发生：</div>
<div dir="ltr">
<ul>
<li>替代的是一个完整的URL (它以http://开始)</li>
<li>替代中包含早期抓取的 $1。</li>
<li>[R=301]标志将浏览器重定向到重写过的网址，在某种意义上说，这是硬性重定向，它是浏览器加载新的页面，并用新的URL地址更新地址栏。</li>
<li>[L]标志的意思是这是最后需要分析的一条规则，重写引擎应该停止了。</li>
</ul>
</div>
<div dir="ltr">如果传入的URL是“http://www.example.com/user/index.html”，那么HTTP_HOST是 beenwww.example.com，重写会创造http://example.com/user/index.html。</p>
<p>如果传入的URL是“http://example.com/user/index.html”，那么HTTP_HOST是beenexample.com，不满足条件，重写引擎将会保持网址不变。</p>
<p><strong><span style="font-size: medium;">禁止盗链</span></strong></div>
<div dir="ltr">盗链，在维基百科中被称为内联链接，是用来描述一个网站读取另一个网站的内容。通常一个网站，读取者，将包括一些其他网站上的媒体文件的链接（让我们说 成是一个图像或视频）——包含内容的主机。在这种情况下，内容主机的服务器会浪费带宽为其他网站提供内容（译者注：图像、视频等）。</p>
<p>对许多人来说，如果其他网站链接他们的内容，这很好。然而，许多人宁愿防止盗链，为了不支付将本网站内容发送到其他网站产生的额为的带宽。</p>
<p>最常见的、基本的防止盗链是的方法将一些网站加进空白页列表，并阻止其他的一切访问。你可以通过检查引用的内容来找出谁正在从你的网站访问那些内容。 HTTP_REFERER头（是的它是这样拼写的）是由正在访问资源的浏览器或客户端设置的。最后，这是不是100％可靠的，但它是禁止大多数盗链的最有 效的方法。因此，你只需验证引用是否在空白页列表中。如果引用是不能接受的（空白或其他人的网站），那么你可以给他们发送禁止警告：</p></div>
<div dir="ltr">
<ol>
<li># 给盗链着发送403禁止访问警告。</li>
<li>RewriteEngine on</li>
<li><span>RewriteCond %{HTTP_REFERER} !^http://example\.net/?.*$ [NC] </span></li>
<li><span>RewriteCond %{HTTP_REFERER} !^http://example\.com/?.*$ [NC] </span></li>
<li><span>RewriteRule \.(gif|jpe?g|png|bmp)$ &#8211; [F,NC] </span></li>
</ol>
</div>
<div dir="ltr">在这里，RewriteRule检查的是任何一个主流类型的图像文件，例如的.gif,.png或.jpg。如果你想保护.flv,.swf或者是其他文件，你可以添加其他扩展到这个列表中。<br />
<!--more--><br />
被允许访问的域名是“example.net”和“example.com”，在这两种情况下，重写条件验证将失败，替代也不会发生。如果有任何其他域 名尝试访问，比如说说“sample.com”企图访问，那么所有的重写条件会验证通过，替代会发生，比且[F]禁止动作将被触发。</p>
<p><strong><span style="font-size: medium;">给盗链者发送一张警告图片</span></strong></div>
<div dir="ltr">当有人试图从你的服务器上读取内容时，前面的例子会返回404禁止访问警告。实际上，你可以更进一步，给盗链者发送你选择的任何资源。例如，您可以发送一 个有用的以文字“盗链不允许”表述的图片警告。这样，其他人能够意识到他们自己的错误，并在他们的主机上保存一份副本。唯一的变化是改变替换方式，并提供 一个已经选好的图片来代替正在被访问的资源：</p>
<ol>
<li><span><span># 重定向盗链者请求为 &#8220;warning.png&#8221; </span></span></li>
<li><span>RewriteEngine on </span></li>
<li><span>RewriteCond %{HTTP_REFERER} !^http://example\.net/?.*$ </span></li>
<li><span>RewriteCond %{HTTP_REFERER} !^http://example\.com/?.*$   [NC] </span></li>
<li><span>RewriteRule \.(gif|jpe?g|png|bmp)$ http://example.com/warning.png [R,NC] </span></li>
</ol>
</div>
<div dir="ltr">注意，这是一个我称之为“硬”或“外部”重定向的例子。该重定向规则在他的替换部分有一个URL和一个[R］标志。</div>
<div dir="ltr"><strong><span style="font-size: medium;">自定义404 错误<br />
</span></strong><br />
一个窍门：你可以用htaccess检查目前的“URL部分”是不是链接到服务器上的实际文件或<a href="http://www.iwanna.cn/tags/web/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Web">Web</a>目录，这是一个创建自定义404“文件未找到”页 面的好方法。例如，如果用户试图读取特定目录中不存在的页面时，你可以重定向它们到任何网页，如Index页面或自定义404页。</div>
<div dir="ltr">
<ol>
<li><span><span># 显示“custom_404.html”页的通用404页</span></span></li>
<li><span># 如果请求的页面不是一个文件或目录 </span></li>
<li><span>#静态重定向：用户的地址栏的内容不变。 </span></li>
<li><span>RewriteEngine on </span></li>
<li><span>RewriteCond %{REQUEST_FILENAME} !-f </span></li>
<li><span>RewriteCond %{REQUEST_FILENAME} !-d </span></li>
<li><span>RewriteRule .* custom_404.html [L] </span></li>
</ol>
<p>这是mod_rewrite文件测试的很好的例子。它同bash shell脚本、甚至是Perl脚本文件测试相似。这里的条件检查REQUEST_FILENAME是不是一个文件或目录。在都不是的情况下，则没有这样的文件反馈给这个请求。</p>
<p>如果传入的请求文件无法找到，那么返回一个“custom404.html”页面。注意有没有[R]标志，所以这是一个静态重定向，而不是硬重定向。用户的地址栏将不会改变，但网页的内容是“custom404.html”，简短而简单。</p>
<p><strong><span style="font-size: medium;">安全第一<br />
</span></strong><br />
如果你有经常使用的mod_rewrite代码片段，并想轻松地分发到其他的服务器或环境中，你可能得要小心。如前所述，任何一个.htaccess文件的无效指令都可能会引起内部服务错误。因此，如果你的代码片段要移动到的环境没有mod_rewrite，你可以先暂停一下。</p>
<p>一个解决这个问题是mod_rewrite模块的“检查“指令”，任何一个模块都有这个指令。只要将你的mod_rewrite代码放到&lt;IfModule&gt;块中，你可以这样设置：</p>
<ol>
<li><span><span>&lt;</span><span>IfModule</span><span> mod_rewrite.c</span><span>&gt;</span><span> </span></span></li>
<li><span> </span></li>
<li><span> # Turn on </span></li>
<li><span> RewriteEngine on </span></li>
<li><span> </span></li>
<li><span> # Always remove www (with a hard redirect) </span></li>
<li><span> RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC] </span></li>
<li><span> RewriteRule ^(.*)$ http://example.com/$1 [<span>R</span><span>=</span><span>301</span><span>,L] </span></span></li>
<li><span> </span></li>
<li><span> # Generic 404 for anyplace on the site </span></li>
<li><span> # &#8230; </span></li>
<li><span> </span></li>
<li><span><span>&lt;/</span><span>IfModule</span><span>&gt;</span><span> </span></span></li>
</ol>
<p><strong><span style="font-size: medium;">结论<br />
</span></strong><br />
我希望本教程能够证明mod_rewrite没有想象的那么恐怖，并且事实上通过精心设计，它的复杂性和访问速度问题都可以避免。</div>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/10/09/2276/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/10/09/2276/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/10/09/2276/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/10/09/2276/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/10/09/2276/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/server/apache/" title="Apache" rel="tag nofollow">Apache</a>, <a href="http://www.iwanna.cn/tags/apache/" title="Apache" rel="tag nofollow">Apache</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/10/19/2321/" title="Apache中 RewriteRule 规则参数介绍 (2009年10月19日)">Apache中 RewriteRule 规则参数介绍</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/10/19/2318/" title="Apache中 RewriteCond 规则参数介绍 (2009年10月19日)">Apache中 RewriteCond 规则参数介绍</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/10/09/2276/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
