Apache的模块mod_rewrite的归纳总结

Apache

1 介绍

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

2 模块的作用

以下URL范例:
很不友好的URL:

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

比较友好的URL:

http://example.com/user/4512/

非常友好的URL:

http://example.com/user/joe/

以上可由mod_rewrite实行URL转换

3 模块的启用

3.1 开启模块

vim /etc/httpd/conf/httpd.conf

去掉以下行的注释:

LoadModule rewrite_module modules/mod_rewrite.so

3.2 修改配置文件

1)主配置文件的修改方法

vim /ect/httpd/httpd.conf

修改如下配置:

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

将其中的:AllowOverride None 改为 AllowOverride All
2)虚拟服务器的配置方法:

vim /ect/httpd/conf.d/www.example.com.conf

找到以下代码段:

<Directory /var/www/www.example.com>
Options FollowSymLinks
AllowOverride All
</Directory>

3.3 重启服务

/etc/init.d/httpd restart

3.4 检查模块是否启用

1)在Apache的配置文件中的“DocumentRoot”定义的目录通过vim编辑index.php
并加入如下内容:

<?php phpinfo(); ?>

2)访问主机的http服务会看到如下显示

3)或者用shell命令测试

apachectl -t -D DUMP_MODULES | grep rewrite

显示如下:

rewrite_module (shared)

4、全局配置文件

在Apache的配置文件中的“DocumentRoot”定义的目录下有一个名字为“.htaccess”的隐藏文件
1)查看命令

ls -la

显示如下:

-rwxrwx---.  1 root apache   412 Dec  2 15:37 .htaccess

2)“.htaccess”的变量前缀
在Apache的配置文件中的“DocumentRoot”定义的目录下

vim test.php

加入如下内容:

<?php
echo $_SERVER['REQUEST_URI']
?>

页面执行输出:

/test.php
mkdir test
mv test.php test

页面执行输出:

/test/test.php

以上变量“REQUEST_URI”如果写入”.htaccess”的出来的结果最前面的”/”都会被去掉。

5 指令

5.1 RewiteRule指令

5.1.1 作用

重写URL

5.1.2 格式

RewiteRule Pattern Substitution [Flages] Pattern — 模式
Substituion — 替换

5.1.3 范例

范例目标:

http://www.example.com/display.php?country=USA&state=California&city=San_Diego

替换为:

http://www.example.com/USA/California/San_Diego

分析步骤:
step1

Pattern:/USA/California/San_Diego
对应
Substitution:/display.php?country=USA&state=California&city=San_Diego

step2

Pattern:/(.*)/(.*)/(.*)
Substitutio:/display.php?country=$1&state=$2&city=$3

— Pattern的USA,California,San_Diego三个参数要我们分别用三个(.*)匹配
— Substitution的USA,California,San_Diego三个变量以$1,$2,$3代替
— RewiteRule支持$1到$9
step3

Pattern:/([a-zA-Z]+)/([a-zA-Z]+)/([a-zA-Z]+)
Substitutio:/display.php?country=$1&state=$2&city=$3

— 细化(.*)的匹配大小写字母([a-zA-Z]+)
step4

Pattern:/?([a-zA-Z]+)/([a-zA-Z]+)/([a-zA-Z]+)
Substitutio:/display.php?country=$1&state=$2&city=$3

— 为了兼容性最前面的斜杠”/”要加上加”?”,表是匹配本身或”?”前面的字符
step5

Pattern:^/?([a-zA-Z]+)/([a-zA-Z]+)/([a-zA-Z]+)$
Substitutio:/display.php?country=$1&state=$2&city=$3

— 最后,但为了明确开始和结束我们需要加上起止符号”^”和”$”
step6

RewiteRule ^/?([a-zA-Z]+)/([a-zA-Z]+)/([a-zA-Z]+)$ /display.php?country=$1&state=$2&city=$3

按照RewiteRule的指令格式,我们得到上式子

5.1.4 规则修正符

— R强制外部重定向
— F禁用URL,返回403HTTP状态码
— G强制URL为GONE,返回410HTTP状态码
— P强制使用代理转发
— L表明当前规则是最后一条规则,停止分析以后规则的重写
— C与下一条规则关联
— T=MIMF-type(force MIME type)强制MIME类型
— NS只用于不是内部子请求
— QSA追加请求字符串
— NE不再输出转移字符(\%3d$1等价于=$1)

5.2 RewriteCond指令

5.2.1 作用

RewriteCond指令相当于RewiterRule的if语句,在一条RewriteRule指令前面可以写一条或多条RewriteCond指令,当自身的模板(pattern)匹配这些条件都才执行紧邻的RewiterRule语句。

RewriteEngine on
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla//5/.0.*
RewriteRule  index.php            index.m.php
RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  index.php            index.L.php 
RewriteRule  index.php            index.b.php

第1行,开启Rewrite引擎
第2行,如果服务器变量%{HTTP_USER_AGENT}匹配到mozilla浏览器,则执行下一行
第3行,默认首页为index.m.php
第4行,如果服务器变量%{HTTP_USER_AGENT}匹配到移动终端浏览器,则执行下一行
第5行,默认首页为index.L.php
第6行,没有符合以上条件则匹配index.b.php

5.2.2 格式

RewriteCond TestString CondPattern [Flages] TestSting — 特使字符串
CondPattern — Cond的匹配模式

5.2.3 范例

1)匹配域名后跳转到指定的页面

RewriteCond %{HTTP_REFERER} (www.cmdschool.org)
RewriteRule (.*)$ weihuzhong.php

第1行,匹配用户访问www.cmdschool.org
第2行,页面套转到weihuzhong.php
2)条件或的使用

RewriteCond %{HTTP_REFERER} (w1.cmdschool.org) [OR]
RewriteCond %{HTTP_REFERER} (w2.cmdschool.org) [OR]
RewriteCond %{HTTP_REFERER} (www.cmdschool.org) 
RewriteRule (.*)$ weihuzhong.php

跟例子(1)一样,不过这是匹配“w1.cmdschool.org”或“w2.cmdschool.org”或“www.cmdschool.org”都跳转到weihuzhong.ph

6 补充知识

6.1 输出服务器所有变量集合

网站跟目录vim编辑test.php,输入如下代码:

<?php
print_r($_SERVER);
?>

输出结果页面右键单击“查看网页源代码”:

Array
(
    [HTTP_HOST] => www.cmdschool.com
    [HTTP_CONNECTION] => close
    [HTTP_CACHE_CONTROL] => max-age=0
    [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36
    [HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch
    [HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8
    [HTTP_COOKIE] => pgv_pvi=4685930496
    [PATH] => /sbin:/usr/sbin:/bin:/usr/bin
    [SERVER_SIGNATURE] =>
Apache/2.2.15 (CentOS) Server at test.kuaijiecaifu.com Port 80
[SERVER_SOFTWARE] => Apache/2.2.15 (CentOS) [SERVER_NAME] => w1.cmdschool.com [SERVER_ADDR] => 192.168.11.253 [SERVER_PORT] => 80 [REMOTE_ADDR] => 123.42.0.25 [DOCUMENT_ROOT] => /var/www/www.cmdschool.org/app/public [SERVER_ADMIN] => root@localhost [SCRIPT_FILENAME] => /var/www/www.cmdschool.org/app/public/test.php [REMOTE_PORT] => 35718 [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_PROTOCOL] => HTTP/1.0 [REQUEST_METHOD] => GET [QUERY_STRING] => a=123 [REQUEST_URI] => /test.php?a=123 [SCRIPT_NAME] => /test.php [PHP_SELF] => /test.php [REQUEST_TIME_FLOAT] => 1449303516.784 [REQUEST_TIME] => 1449303516 )

6.2、单变量输出范例

网站跟目录vim编辑test.php,输入如下代码:

<?php
echo $_SERVER['HTTP_HOST']
?>

以上可根据自己的需求替换对应的服务器变量名称。
输出结果:

www.cmdschool.com

6.3 正则表达式


以下翻译笔者水平有限,仅供参阅!
如有错漏欢迎指正,笔者感激不尽。

6.3.1 起止符

^     #行的开始
$     #行的结束
\A    #字符串的开始
\Z    #字符串的结束
\b    #单词的分界
\B    #非单词分界
\>    #单词的结束

6.3.2 字符类型

\c    #控制字符
\s    #空格
\S    #非空格
\d    #数字
\D    #非数字
\w    #单词
\W    #非单词
\xhh  #十六进制字符hh
\Oxxx #八进制字符xxx

6.3.3 POSIX字符类型

[:upper:]  #大写字母
[:lower:]  #小写字母
[:alpha:]  #所有的字母
[:alnum:]  #数字和字母
[:digit:]  #数字
[:xdigit:] #十六进制数字
[:punct:]  #标点符号
[:blank:]  #空格和跳格
[:space:]  #空格
[:cntrl:]  #控制字符
[:graph:]  #印刷字符
[:print:]  #印刷字符和空格
[:word:]   #数字、字母和下划线

6.3.4、界定符

?=          #前瞻界定符
?!          #否定前瞻
?<=         #回顾界定符
?!=or?<!    #否定回顾
?()         #条件[if then]
?()|        #条件[if then else]
?#          #注释

6.3.5 量词

*     #0或更多
*?    #0或更多,非贪婪模式
+     #一个或更多
+?    #一个或更多,非贪婪模式
?     #0或1
??    #0或1,非贪婪模式
{3}   #精确为3
{3,}  #3或更多
{3,5} #3,4或5
{3,5}? #3,4或5,非贪婪模式

正则表达式的贪婪与非贪婪匹配
如:

String str="abcaxc";
Patter p="ab*c";

贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab*c)。
非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab*c)。

6.3.6、特殊字符

\    #转义字符
\n       #新的一行(逻辑分行)
\r       #回车
\t       #跳格
\v       #垂直跳格
\f       #
\a       #
[\b]     #退格
\e       #Esc
\N{name} #命名字符

6.3.7 字符串替代

$n    #第n个非被动组
$2    #"xyz"在/^(abc(xyz))$/中
$1    #"xyz"在/^(?:abc)(xyz)$/中
$`        #匹配之前的字符串
$'        #匹配之后的字符串
$+        #匹配最后的字符串
$&        #匹配全部的字符串
$_        #输入的全部字符串
$$        #逐字"$"

6.3.8 范围

.       #反逻辑换行(\n相反)
(a|b)   #a或b
(...)   #组
(?:...) #被动组
[abc]   #范围(a或b或c)
[^abc]  #非a或b或c
[a-q]   #a到q的字符
[A-Q]   #大写字母A到Q的字符
[0-7]   #0到7的数字
\n      #第n组或子模式

6.3.9 模式修正符

g    #全局匹配
i    #不分大小写
m    #多行
s    #把字符串当作一行
e    #求值替代
U    #非野蛮模式

6.3.10 通配符

^
$
(
)
< >
|
\
{
[
.
*
+
?

参阅资料:
https://www.addedbytes.com/download/?file=regular-expressions-cheat-sheet-v2/png
http://www.cheatography.com/davechild/cheat-sheets/mod-rewrite/
http://www.smashingmagazine.com/2009/05/introduction-to-advanced-regular-expressions/
http://www.yeeyan.org/articles/view/jcky/59298
正则表达式查询工具:
http://rick.measham.id.au/paste/explain.pl?regex=%5E%28.*%29%24
指令:
http://blog.sina.com.cn/s/blog_6294abe70101bcfz.html
http://www.jb51.net/article/24435.htm

没有评论

发表评论

Apache
如何传递真实IP到Apache后端?

1 前言 一个问题,一篇文章,一出故事。 本章需要实现前端反向代理(Nginx)的服务器需要传递客户 …

Apache
如何配置Apache的安全SSL/TLS?

1 基础知识 1.1 TLS版本现状 – 目前TLS 1.2和TLS 1.3以外的所有协 …

Apache
如何编译安装Apache+PHP7.4.3?

1 前言 笔者平素不喜欢简单的编译安装,因为很多系统管理员为了省事,编译安装的东西没有rpm包安装那 …