Apache之Rewrite和RewriteRule规则梳理以及http强转https的配置总结

一. 简单实例介绍
一般来说,apache配置好http和https后,如果想要做http强转到https,需要设置url重定向规则,大致需要下面几个步骤即可完成配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1)在httpd.conf文件里使下面模块生效
[root@back ~]# cat /usr/local/apache/conf/httpd.conf
.....
LoadModule ssl_module modules/mod_ssl.so                      #打开https功能模块
.....
LoadModule rewrite_module modules/mod_rewrite.so              #打开重写跳转功能模块
 
2)httpd.conf配置文件或者是在httpd-vhost.conf文件里修改
[root@back ~]# cat /usr/local/apache/conf/httpd.conf
.......
DocumentRoot "/data/vhosts"
<Directory "/data/vhosts">
    Options FollowSymLinks MultiViews Includes
    AllowOverride All                                     #AllowOverride None一定要修改为AllowOverride All!!
    Require all granted
</Directory>
 
3)在网站根目录下面添加该文件".htaccess"目录访问控制文件,并添加如下内容:
RewriteEngine on         
RewriteBase /            
RewriteCond %{SERVER_PORT} !^443$   
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]   
 
 
含义是这样的:为了让用户访问传统的http://转到https://上来,用了一下rewrite规则:
第一句:启动rewrite引擎
第三句:rewrite的条件是访问的服务器端口不是443端口
第四句:这是正则表达式,^是开头,$是结束,/?表示有没有/都可以(0或1个),(.*)是任何数量的任意字符
整句的意思是讲:启动rewrite模块,将所有访问非443端口的域名请求,url地址内容不变,将http://变成https://

上面的配置实现了将所有域名的http跳转为https,如果只是针对某一个url的https跳转,则配置情况会有所不同,如下:

1
2
3
4
5
6
7
8
9
10
11
实现单个url类型的https跳转需求:
访问http://bo.kevin.com/beijing/...... 强制跳转到https://bo.kevin.com/beijing/......
配置如下:
 
[root@docker-test2 web]# cat .htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} /beijing
RewriteRule ^(.*$) https://bobo.kevin.com/beijing/ [R,L]
</IfModule>

===========Apache下http跳转至https的案例说明=============
1) 示例一

1
2
3
4
RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} !^/tz.php
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R]

%{SERVER_PORT}     说明访问端口
%{REQUEST_URI}      比如如果url是 http://localhost/tz.php,则是指 /tz.php
%{SERVER_NAME}    比如如果url是 http://localhost/tz.php,则是指 localhost

以上规则的意思是,如果访问的url的端口不是443,且访问页面不是tz.php,则应用RewriteRule这条规则。这样便实现了:访问了 http://localhost/index.php 或者 http://localhost/admin/index.php 等页面的时候会自动跳转到 https://localhost/index.php 或者 https://localhost/admin/index.php,但是访问 http://localhost/tz.php 的时候就不会做任何跳转,也就是说 http://localhost/tz.php 和 https://localhost/tz.php 两个地址都可以访问。

2) 示例二
.htaccess 在每一层独立服务根目录下都存在,例如

1
2
3
4
全部网站根目录为   /var/www/html/.htaccess
士博博客根目录位   /var/www/html/shibo-wordpress/.htaccess
士博论坛根目录位   /var/www/html/shibo-discuz/.htaccess
士博学习根目录位   /var/www/html/shibo-study/.htaccess

HTTP 80 强制转 HTTPS
全站采用https协议访问,所以需要http重定向到https,只需要在.htaccess加入下面规则
在相应的网站根目录新建 .htaccess

例如,在士博博客的网站根目录下,新建/var/www/html/shibo-wordpress/.htaccess,内容如下:

1
2
3
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]

或者内容为:

1
2
3
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [R,L]

强制301重定向 HTTPS

1
2
3
4
5
6
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R=301,L]
</IfModule>

站点绑定多个域名
只允许kevin.con和www.kevin.com 跳转

1
2
3
4
5
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTP_HOST} ^kevin.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.kevin.com [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]

高级用法 (可选)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
RewriteEngine on
 
# 强制HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
 
# 某些页面强制
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
 
# 强制HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
 
# 某些页面强制
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

Apache mod_rewrite实现HTTP和HTTPS重定向跳转

当你的站点使用了HTTPS之后,你可能会想把所有的HTTP请求(即端口80的请求),全部都重定向至HTTPS(即端口443)。这时候你可以用以下的方式来做到:(Apache mod_rewrite)把这段代码放在.htaccess文件,即可实现HTTP到HTTPS的重定向。

1
2
3
4
5
RewriteEngine On
 RewriteBase /
 RewriteCond %{SERVER_PORT} 80
 RewriteRule ^(.*)$ https://blog.shibo.com/$1 [R=301,L]
</IfModule>

而当你又想用回HTTP的时候,反过来就可以了:

1
2
3
4
5
6
<IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteBase /
 RewriteCond %{SERVER_PORT} 443
 RewriteRule ^(.*)$ https://blog.shibo.com/$1 [R=301,L]
</IfModule>

其中R=301表示Moved Permanently,即告诉搜索引擎或者浏览器下去直接访问后者的地址,如果只是试验性地重定向,可以使用R=302(Found),临时跳转

VirtualHost 添加重定向
需要注意实测以上方法,对于下面需求场景,都无效!!下面项目场景:
1) 在我的根目录下 /var/www/htmp/
2) 配置有多个网站,如士博博客(/var/www/htmp/shibo-blog/)、士博论坛(/var/www/htmp/shibo-forum/)、士博学习(/var/www/htmp/shibo-study/)等
3) 对于士博博客的http请求,全部定向到https博客;对于士博论坛的http请求,全部定向到https论坛;

最后,解决方案是在 VirtualHost 节点里,添加如下配置:

1
2
3
RewriteEngine on
RewriteCond   %{HTTPS} !=on
RewriteRule   ^(.*)  https://%{SERVER_NAME}$1 [L,R]

完整配置参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# blog
<VirtualHost *:80>
    ServerAdmin yanggang_2050@163.com
    DocumentRoot /var/www/html/wordpress
    ServerName blog.shibo.com
  
    RewriteEngine on
    RewriteCond   %{HTTPS} !=on
    RewriteRule   ^(.*)  https://%{SERVER_NAME}$1 [L,R]
  
    DirectoryIndex index.php
    ErrorLog /var/log/blog.shibo.com-error_log
    CustomLog /var/log/blog.shibo.com-access_log common
</VirtualHost>

3) 示例三

在启用了https之后,还要保证之前的http端口可以打开,http的80端口是有两个网址的,所以这就导致需要把原来的带www和不带www的kevin.com域名同时指定一个https网址上面(https://kevin.com),需要做两个Apache的301重定向,这个其实是很简单的,最简单的做法是直接在 .htaccess文件中添加两个301即可,如下所示:

1
2
3
4
5
rewritecond %{http_host} ^www.kevin.com [nc
RewriteRule ^(.*)?$ https://kevin.com/$1 [R=301,L] 
   
RewriteCond %{SERVER_PORT} !^443$ 
RewriteRule ^(.*)?$ https://kevin.com/$1 [R=301,L]

第一个 301 很自然就是带 www 的跳转到新的 https 上面了,而下面的301重定向则是判断如果端口不是80的话,则进行重定向,这样的话,带www和不带www的域名就一起跳转到 https 一个网址上面了,当然这种全站做301的方法是比较暴力的,通常情况下我们只要把主域名做个301就可以了,我这里是因为启用了原来的两个域名。

4) 示例四:一些其它的 Apache http 跳转到 https 的方法

方法1

1
2
3
4
5
6
RewriteEngine On 
RewriteBase / 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://kevin.com/$1 [R=301,L] 
 
#这样跳转的好处是独立IP主机也支持,访问ip能自动跳转到https

方法2

1
2
3
4
5
RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)?$ https://%{SERVER_NAME}/$1 [R=301,L]
 
#整站跳转

方法3

1
2
3
4
5
6
7
RewriteEngine on
RewriteBase /yourfolder
RewriteCond %{SERVER_PORT} !^443$
#RewriteRule ^(.*)?$ https://%{SERVER_NAME}/$1 [R=301,L]
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
 
#以上至针对某个目录跳转, yourfolder就是目录名

方法4

1
2
3
4
5
6
7
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} /beijing
RewriteRule ^(.*$) https://test.kevin.com/beijing/ [R,L]
 
#针对url中的次级path路径,比如上面的beijing,上面配置可以实现:
访问http://test.kevin.com/beijing/....  跳转到 https://test.kevin.com/beijing/.....

方法5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 强制HTTPS方式访问,对WWW或顶级域名不做跳转。
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.kevin.com/$1 [L,R=301]
 
#强制HTTPS方式访问,并自动将顶级域名跳转到WWW。
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.kevin.com$ [NC]
RewriteRule ^(.*)$ https://www.kevin.com/$1 [L,R=301]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.kevin.com/$1 [L,R=301]
 
#强制HTTPS方式访问,并自动将WWW跳转到顶级域名。
RewriteEngine On
RewriteCond %{HTTP_HOST} !^kevin.com$ [NC]
RewriteRule ^(.*)$ https://kevin.com/$1 [L,R=301]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://kevin.com/$1 [L,R=301]

方法6

1
2
3
4
5
6
redirect 301 /你的网页 https://你的主机+网页
 
#针对某个网页跳转
 
比如:
redirect 301 /beijing.html https://www.kevin.com/beijing.html

方法7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
下面是一个http跳转https的配置
修改根目录.htaccess文件,内容配置如下:
 
<IfModule mod_rewrite.c>
 Options +FollowSymlinks
 RewriteEngine On
 
#thinkphp去掉index.php
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
 
 #http自动跳转到https
 RewriteCond %{SERVER_PORT} !^443$
 
 #只有匹配对应的域名才会跳转
 RewriteCond %{SERVER_NAME} ^hrsc.cc|www.hrsc.cc$
 RewriteRule (.*) https://%{SERVER_NAME}/$1 [R]
 
</IfModule>

                          Apache的https证书免费申请和http->https跳转配置                         

免费https证书可以参考 (apache和nginx都可以使用,效果很强悍!):
https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc
https://my.oschina.net/jianhui1980/blog/1612469
https://www.cnblogs.com/jxlwqq/p/7492274.html (推荐用这个链接,智能从apache配置中自动完成配置, 不需要指定网站根目录)

配置记录如下 (确保服务器的80和443端口在防火墙里已经提前放行):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
===========================================================================================
配置http:
   
[root@test-web-php extra]# cat httpd-vhosts.conf
<VirtualHost *:80>
    ServerAdmin webmaster@example.com
    DocumentRoot "/www/wwwroot/www.kevin.com/web"
    ServerName 0207917c.www.kevin.com
    ServerAlias www.kevin.com
    errorDocument 404 /404.html
    ErrorLog "/www/wwwlogs/www.kevin.com-error_log"
    CustomLog "/www/wwwlogs/www.kevin.com-access_log" combined
       
    #DENY FILES
     <Files ~ (\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)$>
       Order allow,deny
       Deny from all
    </Files>
       
    #PHP
    <FilesMatch \.php$>
            SetHandler "proxy:unix:/tmp/php-cgi-70.sock|fcgi://localhost"
    </FilesMatch>
       
    #PATH
    <Directory "/www/wwwroot/www.kevin.com/web">
        SetOutputFilter DEFLATE
        Options FollowSymLinks
        AllowOverride All
        Require all granted
        DirectoryIndex index.php index.html index.htm default.php default.html default.htm
    </Directory>
</VirtualHost>
   
===========================================================================================
配置https:
   
[root@test-web-php extra]# cat httpd-ssl.conf
Listen 0.0.0.0:443
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLPassPhraseDialog  builtin
SSLSessionCache        "shmcb:/www/server/apache/logs/ssl_scache(512000)"
SSLSessionCacheTimeout  300
    
<VirtualHost *:443>
    ServerAdmin webmaster@example.com
    DocumentRoot "/www/wwwroot/www.kevin.com/web"
    ServerName  www.kevin.com
    ServerAlias www.kevin.com
    errorDocument 404 /404.html
    SSLEngine on
    SSLCertificateFile "/home/ubuntu/www/ssl/cert.pem"
    SSLCertificateKeyFile "/home/ubuntu/www/ssl/key.pem"
    SSLCertificateChainFile "/home/ubuntu/www/ssl/fullchain.pem"
    ErrorLog "/www/wwwlogs/www.kevin.com-error_log"
    CustomLog "/www/wwwlogs/www.kevin.com-access_log" combined
       
    #DENY FILES
     <Files ~ (\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)$>
       Order allow,deny
       Deny from all
    </Files>
       
    #PHP
    <FilesMatch \.php$>
            SetHandler "proxy:unix:/tmp/php-cgi-70.sock|fcgi://localhost"
    </FilesMatch>
       
    #PATH
    <Directory "/www/wwwroot/www.kevin.com/web">
        SetOutputFilter DEFLATE
        Options FollowSymLinks
        AllowOverride All
        Require all granted
        DirectoryIndex index.php index.html index.htm default.php default.html default.htm
    </Directory>
</VirtualHost>
   
===========================================================================================
配置http->https强转
   
[root@test-web-php extra]# cat /www/wwwroot/www.kevin.com/web/.htaccess
<IfModule mod_rewrite.c>
    Options +FollowSymlinks -Multiviews
    RewriteEngine on
    
    # RewriteBase /
     RewriteCond %{SERVER_PORT} !^443$
     RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
    
    # if a directory or a file exists, use it directly
    RewriteCond %{REQUEST_FILENAME} !-f
    
    # otherwise forward it to index.php
    RewriteRule . index.php
</IfModule>
# General setting to properly handle LimeSurvey paths
# AcceptPathInfo on
   
===========================================================================================
证书路径:
   
[root@test-web-php extra]# ll /home/ubuntu/www/ssl/
total 12
-rw-r--r-- 1 root root 1903 May 23 00:53 cert.pem
-rw-r--r-- 1 root root 3551 May 23 00:53 fullchain.pem
-rw------- 1 root root 1679 May 23 00:53 key.pem

二. Apache中 RewriteRule跳转规则参数

Apache模块mod_rewrite提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操作机制。此URL操作可以依赖于各种测试,比如服务器变量、环境变量、HTTP头、时间标记,甚至各种格式的用于匹配URL组成部分的查找数据库。

mod_rewrite模块可以操作URL的所有部分(包括路径信息部分),在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效,还可以生成最终请求字符串。此重写操作的结果可以是内部子处理,也可以是外部请求的转向,甚至还可以是内部代理处理。

以下重点介绍下RewriteRule 的规则以及参数说明。RewriteRule指令是重写引擎的根本。此指令可以多次使用。每个指令定义一个简单的重写规则。这些规则的定义顺序尤为重要——在运行时,规则是按这个顺序逐一生效的。

配置格式:
RewriteRule Pattern Substitution [flags]

1) Pattern是一个作用于当前URL的perl兼容的正则表达式。
"当前URL"是指该规则生效时刻的URL的值。它可能与被请求的URL截然不同,因为其他规则可能在此之前已经发生匹配并对它做了改动。

2) Substitution是当原始URL与Pattern相匹配时,用来替代(或替换)的字符串。除了纯文本,还可以包含:
-  对Pattern的反向引用($N)
-  对最后匹配的RewriteCond的反向引用(%N)
-  规则条件测试字符串(%{VARNAME})中的服务器变量
-  映射函数调用(${mapname:key|default})

3) [flags]标记作为RewriteRule指令的第三个参数,是一个包含以逗号分隔的下列标记的列表:

3.1) 'chain|C'(链接下一规则)
此标记使当前规则与下一个规则相链接。它产生这样的效果:
如果一个规则被匹配,则继续处理其后继规则,也就是这个标记不起作用;
如果该规则不被匹配,则其后继规则将被跳过。

比如:
在一个目录级规则中执行一个外部重定向时,你可能需要删除".www"(此处不应该出现".www")。
'cookie|CO=NAME:VAL:domain[:lifetime[:path]]'(设置cookie):在客户端设置一个cookie。cookie的名称是NAME,值是VAL。
domain是该cookie的域,比如'.apache.org',可选的lifetime是cookie的有效期(分钟),可选的path是cookie的路径。

3.2) 'env|E=VAR:VAL'(设置环境变量)
此标记将环境变量VAR的值设为VAL,VAL可以包含可扩展的正则表达式反向引用($N和%N)。此标记可以多次使用以设置多个变量。
这些变量可以在其后许多情况下被间接引用,通常是在XSSI(<!--#echo var="VAR"-->)或CGI($ENV{'VAR'})中,也可以在后继的
RewriteCond指令的CondPattern参数中通过%{ENV:VAR}引用。使用它可以记住从URL中剥离的信息。

3.3) 'forbidden|F'(强制禁止URL)
强制禁止当前URL,也就是立即反馈一个HTTP响应码403(被禁止的)。使用这个标记,可以链接若干个RewriteConds来有条件地阻塞某些URL。

3.4) 'gone|G'(强制废弃URL)
强制当前URL为已废弃,也就是立即反馈一个HTTP响应码410(已废弃的)。使用这个标记,可以标明页面已经被废弃而不存在了。

3.5) 'handler|H=Content-handler'(强制指定内容处理器)
强自制定目标文件的内容处理器为Content-handler。例如,用来模拟mod_alias模块的ScriptAlias指令,以强制映射文件夹内的所有文件都
由"cgi-script"处理器处理。

3.6) 'last|L'(结尾规则)
立即停止重写操作,并不再应用其他重写规则。它对应于Perl中的last命令或C语言中的break命令。
这个标记用于阻止当前已被重写的URL被后继规则再次重写。例如,使用它可以重写根路径的URL('/')为实际存在的URL(比如:'/e/www/')。

3.7) 'next|N'(从头再来)
重新执行重写操作(从第一个规则重新开始)。此时再次进行处理的URL已经不是原始的URL了,而是经最后一个重写规则处理过的URL。
它对应于Perl中的next命令或C语言中的continue命令。此标记可以重新开始重写操作(立即回到循环的开头)。但是要小心,不要制造死循环!

3.8) 'nocase|NC'(忽略大小写)
它使Pattern忽略大小写,也就是在Pattern与当前URL匹配时,'A-Z'和'a-z'没有区别。

3.9) 'noescape|NE'(在输出中不对URI进行转义)
此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下,特殊字符('%', '$', ';'等)会被转义为等值的十六进制编码('%25', '%24', '%3B'等)。
此标记可以阻止这样的转义,以允许百分号等符号出现在输出中,比如:RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE] ,可以使'/foo/zed转向到一个安全的请求'/bar?arg=P1=zed'。

3.10) 'nosubreq|NS'(不对内部子请求进行处理)
在当前请求是一个内部子请求时,此标记强制重写引擎跳过该重写规则。比如,在mod_include试图搜索目录默认文件(index.xxx)时,Apache会在内部产生子请求。对于子请求,重写规则不一定有用,而且如果整个规则集都起作用,它甚至可能会引发错误。所以,可以用这个标记来排除某些规则。
使用原则:如果你为URL添加了CGI脚本前缀,以强制它们由CGI脚本处理,但对子请求处理的出错率(或资源开销)很高,在这种情况下,可使用这个标记。

3.11) 'proxy|P'(强制为代理)
此标记使替换成分被内部地强制作为代理请求发送,并立即中断重写处理,然后把处理移交给mod_proxy模块。
你必须确保此替换串是一个能够被mod_proxy处理的有效URI(比如以http://hostname开头),否则将得到一个代理模块返回的错误。
使用这个标记,可以把某些远程成分映射到本地服务器域名空间,从而增强了ProxyPass指令的功能。
注意:要使用这个功能,必须已经启用了mod_proxy模块。

3.12) 'passthrough|PT'(移交给下一个处理器)
此标记强制重写引擎将内部request_rec结构中的uri字段设置为filename字段的值,这个小小的修改使得RewriteRule指令的输出能够被(从URI转换到文件名的)Alias, ScriptAlias, Redirect等指令进行后续处理。

举一个能说明其含义的例子:
如果要将/abc重写为/def, 然后再使用mod_alias将/def转换为/ghi,可以这样:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi

如果省略了PT标记,虽然将uri=/abc/...重写为filename=/def/...的部分运作正常,但是后续的mod_alias在试图将URI转换到文件名时会遭遇失效。
注意:如果需要混合使用多个将URI转换到文件名的模块时,就必须使用这个标记。此处混合使用mod_alias和mod_rewrite就是个典型的例子。

3.13) 'qsappend|QSA'(追加查询字符串)
此标记强制重写引擎在已有的替换字符串中追加一个查询字符串,而不是简单的替换。如果需要通过重写规则在请求串中增加信息,就可以使用这个标记。

3.14) 'redirect|R [=code]'(强制重定向)
若Substitution以http://thishost[:thisport]/(使新的URL成为一个URI)开头,可以强制性执行一个外部重定向。如果没有指定code,则产生一个HTTP响应码302(临时性移动)。如果需要使用在300-400范围内的其他响应代码,只需在此指定即可(或使用下列符号名称之一:temp(默认), permanent, seeother)。使用它可以把规范化的URL反馈给客户端,如将"/~"重写为"/u/",或始终对/u/user加上斜杠,等等。

注意:在使用这个标记时,必须确保该替换字段是一个有效的URL。否则,它会指向一个无效的位置!并且要记住,此标记本身只是对URL加上http://thishost[:thisport]/前缀,重写操作仍然会继续进行。通常,你还会希望停止重写操作而立即重定向,那么就还需要使用'L'标记。

3.15) 'skip|S=num'(跳过后继规则)
此标记强制重写引擎跳过当前匹配规则之后的num个规则。它可以模拟if-then-else结构:最后一个规则是then从句,而被跳过的skip=N个规则是else从句。注意:它和'chain|C'标记是不同的!

3.16)'type|T=MIME-type'(强制MIME类型)
强制目标文件的MIME类型为MIME-type,可以用来基于某些特定条件强制设置内容类型。比如,下面的指令可以让.php文件在以.phps扩展名调用的情况下由mod_php按照PHP源代码的MIME类型(application/x-httpd-php-source)显示:RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]

===========RewriteRule跳转设置案例===========
下列配置内容都写到.htaccess文件中,且 .htaccess文件放到apache站点根目录下.

1) 如果http://kevin.com/foo/bar不存在,则跳转到http://other.kevin.com/foo/bar  (.htaccess文件放在kevin.com域名的root根目录下)

1
2
3
4
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://other.kevin.com/$1 [R]

2) 将http://kevin.com/foo/bar的GET请求重定向到http://kevin.com/bar(或是将http://kevin.com/foo/bar.html请求重定向到http://kevin.com/bar.html)。用PHP程序处理POST请求,而不是试图重定向一个帖子(这不太可能奏效)。 (.htaccess文件放在kevin.com域名的root根目录下):

1
2
3
4
5
RewriteEngine On
RewriteCond   %{REQUEST_METHOD}   GET
RewriteRule   ^/?([^/]*\.html?|[^\./]*)[:;,\.]*$   /$1   [R,L,NS]
RewriteCond   %{REQUEST_METHOD}   POST
RewriteRule   ^/?([^/]*\.html?|[^\./]*)[:;,\.]*$   /foo/show.php   [L,NS]

3) 用一个PHP程序/foo/show.php.处理对没有扩展名的top-level.html文件和文件的所有请求.实现http://www.kevin.com/bobo跳转到http://www.kevin.com/bobo.html  (.htaccess文件放在www.kevin.com域名的root根目录下):

1
RewriteRule   ^/?([^/]*\.html?|[^\./]*)[:;,\.]*$   /foo/show.php   [L,NS]

三、Apache Rewrite 规则详解

1) Rewrite规则简介:
Rewirte主要的功能就是实现URL的跳转,它的正则表达式是基于Perl语言。可基于服务器级的(httpd.conf)和目录级的(.htaccess)两种方式。如果要想用到rewrite模块,必须先安装或加载rewrite模块。方法有两种一种是编译apache的时候就直接安装rewrite模块,别一种是编译apache时以DSO模式安装apache,然后再利用源码和apxs来安装rewrite模块。

基于服务器级的(httpd.conf)有两种方法:
一种是在httpd.conf的全局下直接利用RewriteEngine on来打开rewrite功能;
另一种是在局部里利用RewriteEngine on来打开rewrite功能;

下面将会举例说明,需要注意的是,必须在每个virtualhost里用RewriteEngine on来打开rewrite功能。否则virtualhost里没有RewriteEngine on, 它里面的规则也不会生效。

基于目录级的(.htaccess),要注意一点那就是必须打开此目录的FollowSymLinks属性且在.htaccess里要声明RewriteEngine on。

2) 案例说明:

案例一
下面是在一个虚拟主机里定义的规则。功能是把client请求的主机前缀不是www.kevin.com和192.168.100.29都跳转到主机前缀为http://www.kevin.com,避免当用户在地址栏写入http://kevin.com时不能以会员方式登录网站。

1
2
3
4
5
6
7
8
9
10
11
NameVirtualHost 192.168.100.8:80
 
ServerAdmin
DocumentRoot "/web/webapp"
ServerName www.kevin.com.cn
ServerName kevin.com.cn
RewriteEngine on
RewriteCond   %{HTTP_HOST}   !^www.kevin.cn   [NC]  
RewriteCond   %{HTTP_HOST}   !^192.168.10.29   [NC]  
RewriteCond   %{HTTP_HOST}   !^$  
RewriteRule   ^/(.*)   http://www.kevin.cn/  [L] 

以上配置解释:
RewriteEngine on      表示打开rewirte功能
RewriteCond %{HTTP_HOST} !^www.kevin.com [NC]       表示声明Client请求的主机中前缀不是www.kevin.com,[NC]的意思是忽略大小写
RewriteCond %{HTTP_HOST} !^192.168.100.29 [NC]       表示声明Client请求的主机中前缀不是192.168.100.29,[NC]的意思是忽略大小写
RewriteCond %{HTTP_HOST} !^$       表示声明Client请求的主机中前缀不为空
RewriteRule ^/(.*) http://www.kevin.com/ [L]       表示如果Client请求的主机中的前缀符合上述条件,则直接进行跳转到http://www.kevin.com/,[L]意味着立即停止重写操作,并不再应用其他重写规则。这里的.*是指匹配所有URL中不包含换行字符,()括号的功能是把所有的字符做一个标记,以便于后面的应用。$1就是引用前面里的(.*)字符。

案例二
将输入 test.kevin.com 的域名时跳转到tech.kevin.com

1
2
3
4
5
6
7
8
listen 8080
NameVirtualHost 192.168.10.25:8080
ServerAdmin
DocumentRoot  "/usr/local/www/apache22/data1/"
ServerName  tech.kevin.com
RewriteEngine on
RewriteCond   %{HTTP_HOST}   ^test.kevin.com  [NC]
RewriteRule   ^/(.*)   tech.kevin.com  [L]

3) Apache mod_rewrite规则重写的标志一览(上面其实已经介绍了)
3.1)  R[=code](force redirect) 强制外部重定向
强制在替代字符串加上http://thishost[:thisport]/前缀重定向到外部的URL.如果code不指定,将用缺省的302 HTTP状态码。
3.2)  F(force URL to be forbidden)禁用URL,返回403HTTP状态码。
3.3)  G(force URL to be gone) 强制URL为GONE,返回410HTTP状态码。
3.4)  P(force proxy) 强制使用代理转发。
3.5)  L(last rule) 表明当前规则是最后一条规则,停止分析以后规则的重写。
3.6)  N(next round) 重新从第一条规则开始运行重写过程。
3.7)  C(chained with next rule) 与下一条规则关联
如果规则匹配则正常处理,该标志无效,如果不匹配,那么下面所有关联的规则都跳过。
3.8)  T=MIME-type(force MIME type) 强制MIME类型
3.9)  NS (used only if no internal sub-request) 只用于不是内部子请求
3.10)  NC(no case) 不区分大小写
3.11)  QSA(query string append) 追加请求字符串
3.12)  NE(no URI escaping of output) 不再输出转义特殊字符
例如:

1
RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]         #能正确的将/foo/zoo转换成/bar?arg=P1=zed

3.13)  PT(pass through to next handler) 传递给下一个处理
例如:

1
2
RewriteRule ^/abc(.*) /def$1 [PT]      #将会交给/def规则处理
lias /def /ghi

3.14)  S=num(skip next rule(s)) 跳过num条规则
3.15)  E=VAR:VAL(set environment variable) 设置环境变量

4) Apache rewrite例子集合
在httpd中将一个域名转发到另一个域名,新域名为www.kevin.com, 更加简短好记。这时需要将原来的域名kevin.cn, 以及论坛所在地址kevin.com/forums/定向到新的域名,以便用户可以找到,并且使原来的论坛 URL 继续有效而不出现 404 未找到,比如原来的http://www.kevin.com/forums/f60.html, 让它在新的域名下继续有效,点击后转发到http://bbs.kevin.com/f60.html, 这就需要用apache的Mod_rewrite功能来实现。
在.htaccess中添加下面的重定向规则:

1
2
3
4
5
6
7
RewriteEngine On
# Redirect webhosting-kevin.com/forums to bbs.kevin.com
RewriteCond   %{REQUEST_URI}   ^/forums/
RewriteRule    /forums/(.*)    http://bbs.kevin.com/$1   [R=permanent,L]
# Redirect webhosting-kevin.com to kevin.com
RewriteCond   %{REQUEST_URI}   !^/forums/
RewriteRule   /(.*)   http://www.kevin.com/$1   [R=permanent,L]

5) URL重定向

5.1) 案例一
访问   http://www.kevin.com/xxx.php   重定向跳转到   http://www.kevin.com/xxx/
访问   http://yyy.kevin.com   重定向跳转到   http://www.kevin.com/user.php?username=yyy

1
2
3
4
5
6
7
8
RewriteEngine On
RewriteCond   %{HTTP_HOST}   ^www.kevin.com
RewriteCond   %{REQUEST_URI}   !^user\.php$
RewriteCond   %{REQUEST_URI}   \.php$
RewriteRule    (.*)\.php$   http://www.kevin.com/$1/  [R]
RewriteCond   %{HTTP_HOST}   !^www.kevin.com
RewriteRule   ^(.+) %{HTTP_HOST}   [C]
RewriteRule   ^([^\.]+)\.kevin\.com   http://www.kevin.com/user.php?username=$1

5.2) 例子二
/type.php?typeid=*   重定向跳转到   /type*.html
/type.php?typeid=*&page=*    重定向跳转到   /type*page*.html

1
2
RewriteRule   ^/type([0-9]+).html$   /type.php?typeid=$1   [PT]
RewriteRule   ^/type([0-9]+)page([0-9]+).html$   /type.php?typeid=$1&page=$2   [PT]

6) 使用Apache的URL Rewrite配置多用户虚拟服务器
要实现这个功能,首先要在DNS服务器上打开域名的泛域名解析(自己做或者找域名服务商做)。
比如,我就把 *.kevin.com和 *.zzz.net全部解析到了我的这台Linux Server上。然后,看一下我的Apache中关于*.kevin.com的虚拟主机的设定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#*.com,*.kevin.net
 
ServerAdmin
DocumentRoot  /home/www/www.kevin.com
ServerName dns.kevin.com
ServerAlias dns.kevin.com kevin.com kevin.net *.kevin.com *.kevin.net
CustomLog /var/log/httpd/zzz/access_log.log" common
ErrorLog /var/log/httpd/zzz/error_log.log"
AllowOverride None
Order deny,allow
#AddDefaultCharset GB2312
 
 
RewriteEngine on
RewriteCond   %{HTTP_HOST}   ^[^.]+\.zzz\.(com|net)$
RewriteRule   ^(.+) %{HTTP_HOST}$1  [C]
RewriteRule   ^([^.]+)\.zzz\.(com|net)(.*)$   /home/www/www.kevin.com/sylvan$3?un=$1&%{QUERY_STRING}   [L]

在上面这段设置中,把*.kevin.net和*.kevin.com 的Document Root都设定到了/home/www/www.kevin.com,后面都配置了URL Rewrite规则。
RewriteEngine on      #打开URL Rewrite功能
RewriteCond %{HTTP_HOST} ^[^.]+.zzz.(com|net)$     #匹配条件,如果用户输入的URL中主机名是类似 xxxx.kevin.com 或者 xxxx.kevin.net 就执行下面一句
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]    #把用户输入完整的地址(GET方式的参数除外)作为参数传给下一个规则,[C]是Chain串联下一个规则的意思
RewriteRule ^([^.]+)\.zzz\.(com|net)(.*)$ /home/www/www.kevin.com/sylvan$3?un=$1&%{QUERY_STRING} [L]
# 最关键的是这一句,使用证则表达式解析用户输入的URL地址,把主机名中的用户名信息作为名为un的参数传给/home/www/www.kevin.com目录下的脚本,并在后面跟上用户输入的GET方式的传入参数。并指明这是最后一条规则([L]规则)。注意,在这一句中指明的重写后的地址用的是服务器上的绝对路径,这是内部跳转。如果使用http://xxxx这样的URL格式,则被称为外部跳转。使用外部跳转的话,浏览着的浏览器中的URL地址会改变成新的地址,而使用内部跳转则浏览器中的地址不发生改变,看上去更像实际的二级域名虚拟服务器。

这样设置后,重启Apache服务器,测试一下,就大功告成了!

四、分享13个mod_rewrite 应用实例

1) 给子域名加www标记

1
2
3
RewriteCond   %{HTTP_HOST}   ^([a-z.]+)?example\.com$ [NC]
RewriteCond   %{HTTP_HOST}   !^www\. [NC]
RewriteRule   .?   http://www.%1example.com%{REQUEST_URI}   [R=301,L]

这个规则抓取二级域名的%1变量,如果不是以www开始,那么就加www,以前的域名以及{REQUEST_URI}会跟在其后。

2) 去掉域名中的www标记

1
2
RewriteCond   %{HTTP_HOST}   !^example\.com$   [NC]
RewriteRule   .?   http://example.com%{REQUEST_URI}   [R=301,L]

3) 去掉www标记,但是保存子域名

1
2
RewriteCond   %{HTTP_HOST}   ^www\.(([a-z0-9_]+\.)?example\.com)$   [NC]
RewriteRule   .?   http://%1%{REQUEST_URI}   [R=301,L]

这里,当匹配到1%变量以后,子域名才会在%2(内部原子)中抓取到,而我们需要的正是这个%1变量。

4) 防止图片盗链
一些站长不择手段的将你的图片盗链在他们网站上,耗费你的带宽。你可以加一下代码阻止这种行为。

1
2
3
RewriteCond   %{HTTP_REFERER}   !^$
RewriteCond    %{HTTP_REFERER}   !^http://(www\.)?example\.com/   [NC]
RewriteRule   \.(gif|jpg|png)$   - [F]

如果{HTTP_REFERER}值不为空,或者不是来自你自己的域名,这个规则用[F]FLAG阻止以gif|jpg|png 结尾的URL 
如果对这种盗链你是坚决鄙视的,你还可以改变图片,让访问盗链网站的用户知道该网站正在盗用你的图片。

1
2
3
RewriteCond   %{HTTP_REFERER}   !^$
RewriteCond   %{HTTP_REFERER}   !^http://(www\.)?example\.com/.*$ [NC]
RewriteRule   \.(gif|jpg|png)$   http://你的图片地址   [R=301,L]

除了阻止图片盗链链接,以上规则将其盗链的图片全部替换成了你设置的图片。 
你还可以阻止特定域名盗链你的图片:

1
2
RewriteCond   %{HTTP_REFERER}   !^http://(www\.)?leech_site\.com/   [NC]
RewriteRule   \.(gif|jpg|png)$   - [F,L]

这个规则将阻止域名黑名单上所有的图片链接请求。 
当然以上这些规则都是以{HTTP_REFERER}获取域名为基础的,如果你想改用成IP地址,用{REMOTE_ADDR}就可以了。

5) 如果文件不存在重定向到404页面
如果你的主机没有提供404页面重定向服务,那么我们自己创建。

1
2
3
RewriteCond   %{REQUEST_FILENAME}   !-f
RewriteCond   %{REQUEST_FILENAME}   !-d
RewriteRule   .?   /404.php   [L]

这里-f匹配的是存在的文件名,-d匹配的存在的路径名。这段代码在进行404重定向之前,会判断你的文件名以及路径名是否存在。你还可以在404页面上加一个?url=$1参数:

1
RewriteRule ^/?(.*)$ /404.php?url=$1 [L]

这样,你的404页面就可以做一些其他的事情,例如默认信心,发一个邮件提醒,加一个搜索,等等。

6) 重命名目录

如果你想在网站上重命名目录,试试这个:

1
RewriteRule   ^/?old_directory/([a-z/.]+)$   new_directory/$1   [R=301,L]

在规则里我添加了一个“.”(注意不是代表得所有字符,前面有转义符)来匹配文件的后缀名。

7) 将.html后缀名转换成.php

前提是.html文件能继续访问的情况下,更新你的网站链接。 

1
RewriteRule   ^/?([a-z/]+)\.html$   $1.php   [L]

这不是一个网页重定向,所以访问者是不可见的。让他作为一个永久重定向(可见的),将FLAG修改[R=301,L]。

8) 创建无文件后缀名链接

如果你想使你的PHP网站的链接更加简洁易记-或者隐藏文件的后缀名,试试这个: 

1
RewriteRule   ^/?([a-z]+)$   $1.php   [L]

如果网站混有PHP以及HTML文件,你可以用RewriteCond先判断该后缀的文件是否存在,然后进行替换

1
2
3
4
RewriteCond   %{REQUEST_FILENAME}.php   -f
RewriteRule   ^/?([a-zA-Z0-9]+)$   $1.php   [L]
RewriteCond   %{REQUEST_FILENAME}.html   -f
RewriteRule   ^/?([a-zA-Z0-9]+)$   $1.html   [L]

如果文件是以.php为后缀,这条规则将被执行。

9) 检查查询变量里的特定参数

如果在URL里面有一个特殊的参数,你可用RewriteCond鉴别其是否存在

1
2
RewriteCond   %{QUERY_STRING}   !uniquekey=
RewriteRule   ^/?script_that_requires_uniquekey\.php$   other_script.php   [QSA,L]

以上规则将检查{QUERY_STRING}里面的uniquekey参数是否存在,如果{REQUEST_URI}值为script_that_requires_uniquekey,将会定向到新的URL。 

10)删除查询变量

Apache的mod_rewrite模块会自动辨识查询变量,除非你做了以下改动: 

a).分配一个新的查询参数(你可以用[QSA,L]FLAG保存最初的查询变量) 

b).在文件名后面加一个“?”(比如index.php?)。符号“?”不会在浏览器的地址栏里显示。

11) 用新的格式展示当前URI 

如果这就是我们当前正在运行的URLs:/index.php?id=nnnn。我们非常希望将其更改成/nnnn并且让搜索引擎以新格式展现。首先,我们为了让搜索引擎更新成新的,得将旧的URLs重定向到新的格式,但是,我们还得保证以前的index.php照样能够运行。

实现以上功能,诀窍就在于在查询变量中加了一个访问者看不到的标记符“marker”。我们只将查询变量中没有出现“marker”标记的链接进行重定向,然后将原有的链接替换成新的格式,并且通过[QSA]FLAG在已有的参数加一个“marker”标记。以下为实现的方式: 

1
2
3
4
RewriteCond   %{QUERY_STRING}   !marker
RewriteCond   %{QUERY_STRING}   id=([-a-zA-Z0-9_+]+)
RewriteRule   ^/?index\.php$   %1?   [R=301,L]
RewriteRule   ^/?([-a-zA-Z0-9_+]+)$   index.php?marker&id=$1  [L]

这里,原先的URL:http://www.example.com/index.php?id=nnnn,不包含marker,所以被第一个规则永久重定向到http://www.example.com/nnnn,第二个规则将http://www.example.com/nnnn反定向到http://www.example.com/index.php?marker&id=nnnn,并且加了marker以及id=nnnn两个变量,最后mod_rewrite就开始进行处理过程。

第二次匹配,marker被匹配,所以忽略第一条规则,这里有一个“.”字符会出现在http://www.example.com/index.php?marker&id=nnnn中,所以第二条规则也会被忽略,这样我们就完成了。

注意,这个解决方案要求Apache的一些扩展功能,所以如果你的网站放于在共享主机中会遇到很多障碍。

12) 保证安全服务启用

Apache可以用两种方法辨别你是否开启了安全服务,分别引用{HTTPS}和{SERVER_PORT}变量: 

1
2
3
RewriteCond   %{REQUEST_URI}   ^secure_page\.php$
RewriteCond   %{HTTPS}   !on
RewriteRule   ^/?(secure_page\.php)$   https://www.kevin.com/$1 [R=301,L]

以上规则测试{REQUEST_URI}值是否等于我们的安全页代码,并且{HTTPS}不等于on。如果这两个条件同时满足,请求将被重定向到安全服务URI.另外你可用{SERVER_PORT}做同样的测试,443是常用的安全服务端口 

1
2
3
RewriteCond    %{REQUEST_URI}    ^secure_page\.php$
RewriteCond    %{SERVER_PORT}    !^443$
RewriteRule    ^/?(secure_page\.php)$    https://www.kevin.com/$1   [R=301,L]

13) 在特定的页面上强制执行安全服务 

遇到同一个服务器根目录下分别有一个安全服务域名和一个非安全服务域名,所以你就需要用RewriteCond 判断安全服务端口是否占用,并且只将以下列表的页面要求为安全服务: 

1
2
RewriteCond    %{SERVER_PORT}    !^443$
RewriteRule    ^/?(page1|page2|page3|page4|page5)$    https://www.kevin.com/%1  [R=301,L]

以下是怎样将没有设置成安全服务的页面返回到80端口:

1
2
RewriteCond    %{ SERVER_PORT }   ^443$
RewriteRule   !^/?(page6|page7|page8|page9)$   zzz.com%{REQUEST_URI} [R=301,L]

五、由于有些例子是针对特殊路径或特别情况的,以下列出一些例子供参考:

目标 重写设置 说明
规范化URL RewriteRule   ^/~([^/]+)/?(.*)   /u/$1/$2 [R] 将/~user重写为/u/user的形式
  RewriteRule   ^/([uge])/([^/]+)$   /$1/$2/ [R] 将/u/user末尾漏掉的/补上
     
规范化HostName RewriteCond   %{HTTP_HOST}   !^fully\.qualified\.domain\.name   [NC] 域名不合格
  RewriteCond   %{HTTP_HOST}   !^$ 不空
  RewriteCond   %{SERVER_PORT}   !^80$ 不是80端口
  RewriteRule   ^/(.*)   http://fully.qualified.domain.name:%{SERVER_PORT}/$1   [L,R] 重写
  RewriteCond   %{HTTP_HOST}   !^fully\.qualified\.domain\.name   [NC]  
  RewriteCond   %{HTTP_HOST}   !^$  
  RewriteRule   ^/(.*)   http://fully.qualified.domain.name/$1   [L,R]  
     
URL根目录转移 RewriteEngine on  
  RewriteRule   ^/$   /e/www/ [R] 从/移到/e/www/
     
末尾目录补斜线 RewriteEngine on  
(目录范围内) RewriteBase   /~quux/  
  RewriteRule   ^foo$   foo/   [R] /~quux/foo是一个目录,补/
     
  RewriteEngine on  
  RewriteBase   /~quux/  
  RewriteCond   %{REQUEST_FILENAME}   -d 如果请文件名是个目录
  RewriteRule   ^(.+[^/])$   $1/ [R] URL末尾不是斜线时补上
     
Web集群 RewriteEngine on  
  RewriteMap   user-to-host   txt:/path/to/map.user-to-host 用户-服务器映射
  RewriteMap   group-to-host   txt:/path/to/map.group-to-host 组-服务器映射
  RewriteMap   entity-to-host   txt:/path/to/map.entity-to-host 实体-服务器映射
  RewriteRule   ^/u/([^/]+)/?(.*)   http://${user-to-host:$1|server0}/u/$1/$2 用户均衡
  RewriteRule   ^/g/([^/]+)/?(.*)   http://${group-to-host:$1|server0}/g/$1/$2 组均衡
  RewriteRule   ^/e/([^/]+)/?(.*)   http://${entity-to-host:$1|server0}/e/$1/$2 实体均衡
  RewriteRule   ^/([uge])/([^/]+)/?$   /$1/$2/.www/  
  RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3\  
     
URL根目录搬迁 RewriteEngine on  
  RewriteRule   ^/~(.+)   http://newserver/~$1   [R,L] 到其它服务器
     
所用户名首字母分 RewriteEngine on  
  RewriteRule   ^/~(([a-z])[a-z0-9]+)(.*)   /home/$2/$1/.www$3 内一层括号为$2
     
NCSA imagemap移 RewriteEngine on  
植为mod_imap RewriteRule   ^/cgi-bin/imagemap(.*)   $1   [PT]  
     
多目录查找资源 RewriteEngine on  
  # first try to find it in custom/...  
  RewriteCond   /your/docroot/dir1/%{REQUEST_FILENAME}   -f  
  RewriteRule   ^(.+) /your/docroot/dir1/$1   [L]  
  # second try to find it in pub/...  
  RewriteCond   /your/docroot/dir2/%{REQUEST_FILENAME}   -f  
  RewriteRule   ^(.+)   /your/docroot/dir2/$1   [L]  
  # else go on for other Alias or ScriptAlias directives,  
  RewriteRule   ^(.+)   - [PT]  
     
据URL设置环境变量 RewriteEngine on  
  RewriteRule   ^(.*)/S=([^/]+)/(.*)   $1/$3 [E=STATUS:$2]  
     
虚拟主机 RewriteEngine on  
  RewriteCond   %{HTTP_HOST}   ^www\.[^.]+\.host\.com$ 基于用户名
  RewriteRule   ^(.+)   %{HTTP_HOST}$1   [C]  
  RewriteRule   ^www\.([^.]+)\.host\.com(.*)   /home/$1$2  
     
内外人有别 RewriteEngine on  
  RewriteCond   %{REMOTE_HOST}   !^.+\.ourdomain\.com$ 基于远程主机
  RewriteRule   ^(/~.+)   http://www.somewhere.com/$1   [R,L]  
     
错误重定向 RewriteEngine on  
  RewriteCond   /your/docroot/%{REQUEST_FILENAME}   !-f 不是regular文件
  RewriteRule   ^(.+)   http://webserverB.dom/$1  
     
程序处理特殊协议 RewriteRule   ^xredirect:(.+)   /path/to/nph-xredirect.cgi/$1 \ Xredirect协议
  [T=application/x-httpd-cgi,L]  
     
最近镜像下载 RewriteEngine on  
  RewriteMap   multiplex   txt:/path/to/map.cxan 顶级域名与最近ftp服务器映射
  RewriteRule   ^/CxAN/(.*)   %{REMOTE_HOST}::$1 [C]  
  RewriteRule   ^.+\.([a-zA-Z]+)::(.*)$   ${multiplex:$1|ftp.default.dom}$2   [R,L] 据顶级域名不同提供不同的FTP服务器
     
基于时间重写 RewriteEngine on  
  RewriteCond   %{TIME_HOUR}%{TIME_MIN}   >0700  
  RewriteCond   %{TIME_HOUR}%{TIME_MIN}   <1900  
  RewriteRule   ^foo\.html$   foo.day.html 白天为早晚7点间
  RewriteRule   ^foo\.html$   foo.night.html 其余为夜间
     
向前兼容扩展名 RewriteEngine on  
  RewriteBase /~quux/  
  # parse out basename, but remember the fact  
  RewriteRule   ^(.*)\.html$   $1   [C,E=WasHTML:yes]  
  # rewrite to document.phtml if exists  
  RewriteCond   %{REQUEST_FILENAME}.phtml -f 如果存在$1.phtml则重写
  RewriteRule   ^(.*)$   $1.phtml   [S=1]  
  # else reverse the previous basename cutout  
  RewriteCond   %{ENV:WasHTML}   ^yes$ 如果不存在$1.phtml,则保持不变
  RewriteRule   ^(.*)$   $1.html  
     
文件改名(目录级) RewriteEngine on 内部重写
  RewriteBase   /~quux/  
  RewriteRule   ^foo\.html$   bar.html  
     
  RewriteEngine on 重定向由客户端再次提交
  RewriteBase   /~quux/  
  RewriteRule   ^foo\.html$   bar.html   [R]  
     
据浏览器类型重写 RewriteCond   %{HTTP_USER_AGENT}   ^Mozilla/3.*  
  RewriteRule   ^foo\.html$ foo.NS.html   [L]  
  RewriteCond   %HTTP_USER_AGENT}   ^Lynx/.* [OR]  
  RewriteCond   %{HTTP_USER_AGENT}   ^Mozilla/[12].*  
  RewriteRule   ^foo\.html$   foo.20.html [L]  
  RewriteRule   ^foo\.html$   foo.32.html [L]  
     
动态镜像远程资源 RewriteEngine on  
  RewriteBase   /~quux/  
  RewriteRule   ^hotsheet/(.*)$   http://www.tstimpreso.com/hotsheet/$1   [P] 利用了代理模块
     
  RewriteEngine on  
  RewriteBase   /~quux/  
  RewriteRule   ^usa-news\.html$   http://www.quux-corp.com/news/index.html [P]  
     
反向动态镜像 RewriteEngine on  
  RewriteCond   /mirror/of/remotesite/$1   -U  
  RewriteRule   ^http://www\.remotesite\.com/(.*)$   /mirror/of/remotesite/$1  
     
负载均衡 RewriteEngine on 利用代理实现round-robin效果
  RewriteMap   lb   prg:/path/to/lb.pl  
  RewriteRule   ^/(.+)$   ${lb:$1} [P,L]  
     
  #!/path/to/perl  
  $| = 1;  
  $name = "www"; # the hostname base  
  $first = 1; # the first server (not 0 here, because 0 is myself)  
  $last = 5; # the last server in the round-robin  
  $domain = "foo.dom"; # the domainname  
  $cnt = 0;  
  while () {  
  $cnt = (($cnt+1) % ($last+1-$first));  
  $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);  
  print "http://$server/$_";  
  }  
  ##EOF##  
     
静态页面变脚本 RewriteEngine on  
  RewriteBase   /~quux/  
  RewriteRule   ^foo\.html$   foo.cgi   [T=application/x-httpd-cgi]  
     
阻击机器人 RewriteCond   %{HTTP_USER_AGENT}   ^NameOfBadRobot.*  
  RewriteCond   %{REMOTE_ADDR}   ^123\.45\.67\.[8-9]$  
  RewriteRule   ^/~quux/foo/arc/.+   - [F]  
     
阻止盗连你的图片 RewriteCond   %{HTTP_REFERER}   !^$  
  RewriteCond   %{HTTP_REFERER}   !^http://www.quux-corp.de/~quux/.*$   [NC] 自己的连接可不能被阻止
  RewriteRule   .*\.gif$   - [F]  
     
  RewriteCond   %{HTTP_REFERER}   !^$  
  RewriteCond   %{HTTP_REFERER}   !.*/foo-with-gif\.html$  
  RewriteRule   ^inlined-in-foo\.gif$   - [F]  
     
拒绝某些主机访问 RewriteEngine on  
  RewriteMap   hosts-deny   txt:/path/to/hosts.deny  
  RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}   !=NOT-FOUND   [OR]  
  RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}   !=NOT-FOUND  
  RewriteRule   ^/.*   - [F]  
     
用户授权 RewriteCond   %{REMOTE_IDENT}@%{REMOTE_HOST}   !^friend1@client1.quux-corp\.com$  
  RewriteCond   %{REMOTE_IDENT}@%{REMOTE_HOST}   !^friend2@client2.quux-corp\.com$  
  RewriteCond   %{REMOTE_IDENT}@%{REMOTE_HOST}   !^friend3@client3.quux-corp\.com$  
  RewriteRule   ^/~quux/only-for-friends/   - [F]  
     
外部重写程序模板 RewriteEngine on  
  RewriteMap   quux-map   prg:/path/to/map.quux.pl  
  RewriteRule   ^/~quux/(.*)$   /~quux/${quux-map:$1}  
     
  #!/path/to/perl  
  $| = 1;  
  while (<>) {  
  s|^foo/|bar/|;  
  print $_;  
  }  
     
搜索引擎友好 RewriteRule   ^/products$   /content.php  
  RewriteRule   ^/products/([0-9]+)$   /content.php?id=$1  
  RewriteRule   ^/products/([0-9]+),([ad]*),([0-9]{0,3}),([0-9]*),([0-9]*$)   /marso/content.php?id=$1&sort=$2&order=$3&start=$4  

==============================================================================
针对apache的route路由转发设置,注意下面几个配置点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
1)修改httpd.conf主配置文件
[root@kevin01 ~]# cat /usr/local/apache/conf/httpd.conf
........
LoadModule rewrite_module modules/mod_rewrite.so        #打开重写转发功能模块
 
DocumentRoot "/data/www/public"                                    
<Directory "/data/www/public">                                          # apache的站点根目录注意修改
    Options FollowSymLinks MultiViews Includes
    AllowOverride All                                                             #要将默认的None改为All
    Require all granted
</Directory>
 
DirectoryIndex index.html index.php                                    #网站首页默认读出index.php和index.html
 
2)配置vhosts虚拟主机
[root@kevin01 ~]# cat /usr/local/apache/conf/extra/kevin.conf
<VirtualHost *:80>
   ServerName www.kevin-inc.com
   DocumentRoot /data/www/public
   DirectoryIndex index.php index.html
 
   ErrorLog "/var/log/httpd/www.kevin.com-error_log"
   CustomLog "/var/log/httpd/www.kevin.com-access_log" common
 
</VirtualHost>
 
3)配置站点根目录/data/www/public路径下的.htaccess文件
[root@kevin01 ~]# cat /data/www/public/.htaccess
<IfModule mod_rewrite.c>
  Options +FollowSymlinks -Multiviews
  RewriteEngine On
 
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
 
4)重启apache服务
[root@kevin01 ~]# /usr/local/apache/bin/httpd -t
Syntax OK
[root@kevin01 ~]# /usr/local/apache/bin/httpd -k restart
 
5)另外要注意apache站点根目录下的权限,一定要修改为apache启动用户的权限
[root@kevin01 ~]# ps -ef|grep apache
root      3631     1  0 Oct14 ?        00:00:27 /usr/local/apache/bin/httpd
daemon   13770  3631  0 18:13 ?        00:00:00 /usr/local/apache/bin/httpd
daemon   13775  3631  0 18:13 ?        00:00:00 /usr/local/apache/bin/httpd
 
[root@kevin01 ~]# chown -R daemon.daemon /data/www/public
 
 
==================================================
如果apache是http强转为https关系的route路由转发的配置,基本配置注意点如下:
 
1)配置httpd.conf主配置文件
[root@kevin01 ~]# cat /usr/local/apache/conf/httpd.conf
 
LoadModule ssl_module modules/mod_ssl.so                        #打开https访问的功能模块
 
LoadModule rewrite_module modules/mod_rewrite.so            #打开重写跳转功能模块
 
DocumentRoot "/data/www/public"
<Directory "/data/www/public">
    Options FollowSymLinks MultiViews Includes
    AllowOverride All
    Require all granted
</Directory>
 
DirectoryIndex index.html index.php
 
2)配置vhosts虚拟主机
[root@kevin01 ~]# cat /usr/local/apache/conf/extra/kevin.conf
<VirtualHost *:80>
   ServerName www.kevin.com
   DocumentRoot /data/www/public
   DirectoryIndex index.php index.html
 
   ErrorLog "/var/log/httpd/www.kevin.com-error_log"
   CustomLog "/var/log/httpd/www.kevin.com-access_log" common
 
</VirtualHost>
 
[root@kevin01 ~]# cat /usr/local/apache/conf/extra/httpd-ssl.conf
Listen 443
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLPassPhraseDialog  builtin
SSLSessionCache        "shmcb:/usr/local/apache/logs/ssl_scache(512000)"
SSLSessionCacheTimeout  300
  
<VirtualHost *:443>
DocumentRoot "/data/www/public"
ServerName www.kevin.com
DirectoryIndex index.php index.html
 
SSLEngine on
SSLCertificateFile "/usr/local/apache/conf/ssl/ssl.kevin.com.crt"
SSLCertificateKeyFile "/usr/local/apache/conf/ssl/ssl.kevin.com.key"
     ErrorLog "logs/www.kevin.com-https-error_log"
     CustomLog "logs/www.kevin.com-https-access_log" combined
</VirtualHost>
 
[root@kevin01 ~]# ll /usr/local/apache/conf/ssl/
total 8
-rw-rw-r-- 1 root root 4085 Apr  8  2018 ssl.kevin.com.crt
-rw-rw-r-- 1 root root 1706 Apr  8  2018 ssl.kevin.com.key
 
3)配置站点根目录/data/www/public路径下的.htaccess文件(包括http强转到https的配置)
[root@kevin01 ~]# cat /data/www/public/.htaccess
<IfModule mod_rewrite.c>
  Options +FollowSymlinks -Multiviews
  RewriteEngine On
 
 RewriteCond %{SERVER_PORT} !^443$
 RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
 
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
 
4)重启apache服务
[root@kevin01 ~]# /usr/local/apache/bin/httpd -t
Syntax OK
[root@kevin01 ~]# /usr/local/apache/bin/httpd -k restart
 
5)另外要注意apache站点根目录下的权限,一定要修改为apache启动用户的权限
[root@kevin01 ~]# ps -ef|grep apache
root      3631     1  0 Oct14 ?        00:00:27 /usr/local/apache/bin/httpd
daemon   13770  3631  0 18:13 ?        00:00:00 /usr/local/apache/bin/httpd
daemon   13775  3631  0 18:13 ?        00:00:00 /usr/local/apache/bin/httpd
 
[root@kevin01 ~]# chown -R daemon.daemon /data/www/public
posted @ 2020-11-26 13:42  浮山山主  阅读(393)  评论(0编辑  收藏  举报