重定向和伪静态的基本原理和方法
- 重定向和伪静态的实现方法:
- 通过.htaccess配置
- 工作原理:
.htaccess
文件提供了针对每个目录改变配置的方法。在指定目录中,放置一个.htaccess
文件,此文件的作用域实用于当前目录及其所有的子目录。
- 性能问题: 开启页面的时候要查找所有的上级目录的
.htaccess
。
- 例如:
/wamp/www/project1/public
文件夹下有.htaccess
文件,那么Apache会查找: /wamp/www/project1
, /wamp/www
, /wamp
, /
文件夹下是否有.htaccess
。
- 建议PROD以下的环境,使用
.htaccess
,生产环境需要把所有的重定向文件写到Apache主配置文件中。
- 安全问题:允许用户自行修改服务器的配置,且在不需要重启apache的情况下生效。例如,在没有index文件的情况下,很有可能会暴露文件夹下的所有文件。
- 妥协: 共享服务器,访问量不够大的网站,需要更好的SEO效果的网站,可以妥协掉部分性能。
- 通过Apache的主配置文件字段
- 使用PHP等脚本文件实现(仅限外部重定向)
- 一个基本实例:
- 开启目录重定向的权限:
AllowOverride All
- 配合
.htaccess
配合调试,不需要重启服务器。在Windows下,用CMD创建.htaccess
命令:echo 1 > .htaccess
RewriteEngine on
开启mod_rewrite
RewriteRule ^(.*)\.htm$ $1.html
当浏览器的URL尝试访问test.htm,Apache会在此.htaccess
文件的当前目录下寻找test.html文件。
- Apache重定向原理:
- https://httpd.apache.org/docs/2.4/images/rewrite_process_uri.png
- 防止出现死循环。
mod_rewrite
详解
1. 日志功能
LogLevel
Apache 2.4+
RewriteLog RewriteLogLevel
Apache 2.2
- 配置:
LogLevel alert rewrite:trace8
(LogLevel 不要大于trace2
,或者关闭。)
- 只能在Apache的主配置文件下配置,无法在
.htaccess
进行配置。
- 查看:
apache_error.log
文件
2. RewriteRule语法
- 基本格式:RewriteRule 模式(正则匹配) 替换的URL [flags]
- 模式匹配,支持Perl格式的正则表达式。
- rewrite的预设变量和替换模式的匹配结果: $1
- 多个flag用逗号隔开:[R=302,C]
- R flag 强制外部重定向,后面可以加301和302,如果不加,则默认为302重定向。
- 内部重定向:浏览器的地址栏,URL不会发生变化。
- 外部重定向:浏览器的地址栏,URL会发生变化。
- 针对HTTP协议,301表示永久重定向,302表示临时重定向。
- 实例:
RewriteRule ^/?(.*)\.html$ /src/$1.php [R=302]
- 搜索引擎对当前网站有SEO的评分。如果是永久重定向,那么当前网站的SEO评分,会直接给到新的重定向地址。如果是临时重定向,那么当前网站的SEO评分,不会传递到新的重定向地址,搜索引擎会对新的重定向地址,产生一个新的评分。
- 从SEO优化的角度来说,一般都会使用301重定向。
- C flag 链接下一个规则。与下一条规则形成一个整体,如果第一条规则不匹配,则下一条规则就跳过了。
- 实例:
# 如果第一条规则,如果不匹配,就停止。
RewriteRule ^/?(.*)\.htm$ /\.html [C]
RewriteRule ^/?(.*)\.html$ /\.php
# 如果第一条规则,如果不匹配,不对URI进行替换修改,直接进入第二条规则。
RewriteRule ^/?(.*)\.jsp$ /\.html
RewriteRule ^/?(.*)\.htm$ /\.php
# 如果第一条规则,匹配,但是找不到,就对URI进行替换修改,将匹配后的结果传递给第二条,再匹配第二条规则。
RewriteRule ^/?(.*)\.htm$ /\.html
RewriteRule ^/?(.*)\.html$ /\.php
- L flag 结束规则。立即停止重写操作,并不再应用其它重写规则。当前条件匹配的时候,就不再进行重写,也不再继续进行后面规则的匹配。
- 实例:
RewriteRule ^(.*) first.php [L] # 第一条匹配,对URI替换和重写,结束。
RewriteRule ^(.*) last.php
RewriteRule ^(.*) first.php # 第一条匹配,对URI替换和重写,传递给第二条规则。
RewriteRule ^(.*) last.php # 对URI替换和重写,显示`last.php`。
- NE flag 不对URL中的特殊字符进行hexcode转码。因为匹配项,例如
#
, ?
,
等,后面的代码可能需要使用到,于是要告诉Apache不要对URL进行转义。
- 实例:
# URL 输入为 http://localhost/test.htm
RewriteRule ^(.*)\.htm /index.php#$1 [R] # URL重定向为 http://localhost/index.php%23index
RewriteRule ^(.*)\.htm /index.php#$1 [NE, R] # URL重定向为 http://localhost/index.php#index
- NC flag 不区分大小写。匹配规则,不区分大小写。Apache服务器是区分大小写的。
- 实例:
#
RewriteRule ^test/(.*)\.htm /tmp/\.htm #访问 /Test/1.htm 会直接寻找 Test/1.htm
RewriteRule ^test/(.*)\.htm /tmp/\.htm [NC] #访问 /Test/1.htm 会继续匹配 /tmp/1.htm
- G flag 请求的网页已经失效了 Gone Apache返回服务器410
- 使用情况:例如下载链接,限时访问。打折码过期失效。
- 实例
RewriteRule ^(.*)\.htm - [G] #访问 /Test/1.htm 会直接寻找 Test/1.htm
- QSA flag 截取URI中的查询字符串,保留后面所有的Query String。替换并传递到下一条规则。
- 实例:
# 访问URL为 http://localhost/person/1?name=test
RewriteRule ^persons/(.*)$ /persons.php?person_id=$1 [QSA,R] #http://localhost/index.php?person_id=1&name=test
RewriteRule ^persons/(.*)$ /persons.php?person_id=$1 [R] #http://localhost/index.php?person_id=1
3. RewriteBase语法
RewriteBase URL-path
设置目录级别重写的基本URL。
- 实例
RewriteBase /
RewirteRule ^(.*)\.htm$ $1.html
# 等同于
RewriteRule ^(.*)\.htm$ /\.html [R]
RewriteBase /tmp
RewirteRule ^(.*)\.htm$ $1.html
# 等同于
RewriteRule ^(.*)\.htm$ /tmp/\.html [R]
# 如果没有 / 就会使用DocumentRoot 重定向后的URL会变成 localhost\C:\wamp\www\test.html
RewriteRule ^(.*)\.htm$ $1.html [R]
4. RewriteCond语法说明
- 基本语法:
RewriteCond <testing string> <condition pattern> [flags]
- 指定了在RewriteRule之前的判定条件。可以有多个RewriteCond。
- http://httpd.apache.org/docs/2.4/images/syntax_rewritecond.png
testing string
可以使用$1-$9。取的是RewriteRule的匹配结果。
- 实例
# RewriteRule的条件匹配,如果没有RewriteCond就直接替换。
# 如果有RewriteCond存在,检查当前$1是否等于“test”。如果判定结果是正确,才进行替换。
RewriteCond $1 "test"
RewriteRule ^(.*)\.htm $1.html
testing string
可以使用服务器变量
- 例如
RewriteCond %{HTTP_HOST} "127.0.0.1"
testing string
可以使用%1-%9,表示RewriteCond条件中,最后符合的条件中的组成部分。
- 实例
RewriteCond %{HTTP_HOST} "127.0.0.(.*)" # 这一条RewriteCond有一个正则匹配`(.*)`。将被下一条引用。
RewriteCond %1 "1" # %1 表示上一条RewriteCond的正则匹配的第一个。
RewriteRule ^(.*)\.htm$ http://localhost/\.html [R] # 当URL输入是127.0.0.1的时候,外部重定向为localhost
condition pattern
-d
是否是文件夹
-f
是否是文件
-f
是否是文件,且可以访问
- [flag]
- [OR] 条件判断为“或”。不加就默认为 AND
- 实例
RewriteCond C:/wamp/www -d [OR]
RewriteCond C:/wamp/www2 -d
RewriteCond ^(.*)\.htm $1.html
5. RewriteMap语法说明
- RewriteMap MapType:MapSource
- MapName: Map的命名,给RewriteRule调用
- MapType: map的文件类型,如 txt、rnd
- MapSource: map的文件路径
- 在Apache的配置文件里,配置在的外部。
- 修改map文件,也不需要重启Apache
- txt格式
${MapName: LookupKey | DefaultValue}
- 实例
# 在`httpd.conf`里面创建一个新的配置项:
RewriteMap pages txt:C:/wamp/map.txt
# 在C:/wamp/map.txt文件中,保存配置:
test1 pagetest1
test2 pagetest2
# 在`.htaccess`中配置,或者在apache的主配置文件中配置
RewriteRule ^(.*).shtml ${pages:$1|page}.php # $1 表示拿(.*)去配置
- rnd格式
- 随机映射
RewriteMap servers rnd:c:/wamp/rnd.txt
- 实例
# 在`httpd.conf`里面创建一个新的配置项:
RewriteMap dirs rnd:c:/wamp/dirs.txt
# 在C:/wamp/dirs.txt文件中,保存配置:
URL1 S1|S2|S3 # 当访问一个地址,随机抽取一个值。
URL2 S4|S5
# 在`.htaccess`中配置,或者在apache的主配置文件中配置
RewriteRule ^(.*).shtml /${dirs:$1|root}/\.php
6. 基础正则
.
任意匹配单个字符。
+
匹配1到多个。
*
匹配0到多个。
^
匹配开始位置。
$
匹配结束位置。
?
表面前一个匹配项是可选的,可以有也可以无。
[a-z]
匹配一个a-z的字符
[^a-z]
不允许匹配任何a-z的单个字符
|
或者
- 取值
()
$1表示第一个()
里面匹配的内容
重定向和伪静态的常用案例
1. 临时重定向和永久重定向
- 主要面对的是搜索引擎和机器人。
- 301 永久重定向:不是顶级目录的A页面,做301重定向,到其他目录B,则可以正常收录B页面。搜索引擎会把之前的积分算到新的页面。
- 例如:公司换域名。
- 302 临时重定向:顶级目录的A页面,做302重定向,到其他目录B,则收录的是A页面。
- 如果使用,有可能会被搜索引擎认定为SEO作弊。
2. 防止盗链
```
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$ # 允许http_referer为空的情况,用户直接访问图片
RewriteCond %{HTTP_REFERER} !localhost [NC] # 其它http_referer限定访问
RewriteRule \.(gif|jpg|png)$ - [F,NC] # Forbidden访问
```
3. 限制IP列表
```
# httpd.conf
RewriteMap hosts-deny txt:c:/wamp/hosts.deny # 设置一个映射表,列举哪些IP是禁止访问的。
# hosts.deny
192.168.3.68 deny # 禁止IP 和 结果
# .htaccess
# 获取hosts-deny的IP,与%{REMOTE_ADDR}匹配,如果匹配,则会返回'deny'。
# 由于deny和deny相同,所以RewriteCond为true,则执行RewriteRule的 forbidden。
RewriteEngine on
RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOTFOUND} deny [OR]
RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOTFOUND} deny
RewriteRule ^ - [F] # Forbidden访问
```
4. 限制迅雷
- 迅雷访问的特征,USER_AGENT的匹配。
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC,OR] # 迅雷的user agent包含2.0.50727
RewriteCond %{HTTP_USER_AGENT} ^BlackWido
RewriteRule . abuse.txt # 将迅雷访问重定向到abuse.txt