介绍
在本教程中,我们将激活并学习如何使用Apache2的mod_rewrite
模块来管理URL重写。
本指南分为两部分:第一部分设置了样本Web应用程序,第二部分解释了常用的重写规则。
前提条件
要遵循本教程,您将需要:
- 一个新的 Ubuntu 14.04 Droplet
- 一个 sudo 非 root 用户,您可以通过遵循 [本教程] 的步骤 2 和 3 来设置。
步骤 1 - 安装 Apache
在此步骤中,我们将使用内置的 _package 安装程序,称为 apt-get
. 它极大地简化了管理,并促进了清洁的安装。
首先,更新系统的包索引,以确保旧或过时的包不会干扰安装。
1sudo apt-get update
Apache2 是上述的 HTTP 服务器,也是世界上最常用的服务器。
1sudo apt-get install apache2
有关 Nginx 和 Apache 2 之间最流行的开源 Web 服务器的区别的信息,请参阅 本文。
第2步:启用mod_rewrite
现在,我们需要激活mod_rewrite
。
1sudo a2enmod rewrite
这将激活模块或通知您模块已经生效. 若要将这些更改生效,请重新启动 Apache。
1sudo service apache2 restart
步骤 3 – 设置.htaccess
在本节中,我们将设置一个.htaccess
文件,以便更简单地管理重写规则。
一个.htaccess 文件允许我们修改我们的重写规则,而不需要访问服务器配置文件. 出于这个原因,.htaccess 对您的 Web 应用程序的安全至关重要。
我们需要设置和保护一些其他设置,才能开始。
首先,允许对.htaccess 文件的更改. 使用 'nano' 或您最喜欢的文本编辑器打开默认的 Apache 配置文件。
1sudo nano /etc/apache2/sites-enabled/000-default.conf
在该文件的内部,你会发现<VirtualHost *:80>
块在一行上。
1[secondary_label /etc/apache2/sites-available/default]
2<Directory /var/www/html>
3 Options Indexes FollowSymLinks MultiViews
4 AllowOverride All
5 Order allow,deny
6 allow from all
7</Directory>
您的文件现在应该匹配以下内容. 确保所有块都被正确地插入。
1[secondary_label /etc/apache2/sites-available/default]
2<VirtualHost *:80>
3 <Directory /var/www/html>
4
5 . . .
6
7 </Directory>
8
9 . . .
10</VirtualHost>
要执行这些更改,请重新启动 Apache。
1sudo service apache2 restart
现在,创建.htaccess 文件。
1sudo nano /var/www/html/.htaccess
将这个第一个行添加到新文件的顶部,以激活重写引擎
。
1[secondary_label /var/www/html/.htaccess]
2RewriteEngine on
保存和退出文件。
要确保其他用户只能 read your .htaccess
,请运行以下命令来更新权限。
1sudo chmod 644 /var/www/html/.htaccess
您现在拥有一个操作性的.htaccess 文件,用于管理您的 Web 应用程序的路由规则。
步骤 4 - 设置文件
在本节中,我们将设置一个基本的URL重写,将漂亮的URL转换为实际的代码路径,具体来说,我们将允许用户访问example.com/about
。
我们将开始创建一个名为about.html
的文件。
1sudo nano /var/www/html/about.html
将以下代码复制到 HTML 页面。
1[secondary_label /var/www/html/about.html]
2<html>
3 <head>
4 <title>About Us</title>
5 </head>
6 <body>
7 <h1>About Us</h1>
8 </body>
9</html>
您可以访问您的Web应用程序在your_server_ip/about.html
或example.com/about.html
。 现在注意只有about.html
是可访问的;如果您尝试访问your_server_ip/about
,您将收到一个 Not Found错误。
打开.htaccess 文件。
1sudo nano /var/www/html/.htaccess
第一行后,添加下列内容。
1[secondary_label /var/www/html/.htaccess]
2RewriteRule ^about$ about.html [NC]
您的文件现在应该与以下相同。
1[secondary_label /var/www/html/.htaccess]
2RewriteEngine on
3RewriteRule ^about$ about.html [NC]
恭喜您!您现在可以在您的浏览器中访问example.com/about
!
这是一个很好的简单示例,显示了所有重写规则遵循的通用语法。
^about$
是从 URL 获得匹配的字符串,也就是说,这是浏览器中的浏览器类型。
^
表示 URL 的开始,在example.com/
被删除后。$
表示 URL 的结束about
匹配字符串about
「about.html」是用户访问的实际路径,也就是说,Apache仍然会服务于「about.html」文件。
[NC]
是一个 flag,它忽略了 URL 中的资本化。
按照上面的规则,下列 URL 将指向 about.html
:
example.com/about
example.com/About
example.com/about.html
下列不会:
example.com/about/
example.com/contact
共同模式
在本节中,我们将展示一些常用的指南。
您的 Web 应用程序现在正在运行,并由一个受保护的.htaccess 文件管理。 最简单的例子包括在上面. 我们将在本节中探索另外两个例子。
如果你愿意,你可以设置结果路径的示例文件,但本教程不包括创建HTML和PHP文件;只是重写的规则。
示例 1:用 RewriteRule 简化查询字符串
所有 RewriteRule 都遵循以下格式:
1RewriteRule pattern substitution [flags]
- RewriteRule:指定指令
RewriteRule
- 模式:匹配所需字符串的常规表达式
- 替换:通往实际 URL 的路径 * 旗帜:可修改规则的可选参数
网页应用程序经常使用 query strings,这些字符被附加到一个 URL 使用?
问题标记并使用&
ampersand 划界。当匹配重写规则时,这些字符串被忽略。
1http://example.com/results.php?item=shirt&season=summer
在这个例子中,我们想简化这成为:
1http://example.com/shirt/summer
示例1A:简单取代
使用重写规则,我们可以使用如下:
1[secondary_label /var/www/html/.htaccess]
2RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer
以上是相当自我解释的,因为它实际上将衬衫/夏季
转化为results.php?item=shirt&season=夏季
。
示例1B:匹配选项
然而,我们希望将这一点概括为包括所有季节,因此,我们将如下:
- 指定一系列选项,使用 Boolean 字符,意思是
OR
- 使用
()
组合匹配,然后使用$1
参考组,并为第一个匹配的组合 参考1
。
重写规则现在变成:
1[secondary_label /var/www/html/.htaccess]
2RewriteRule ^shirt/(summer|winter|fall|spring) results.php?item=shirt&season=$1
上面的规则匹配一个衬衫/
的URL,然后是指定的季节,该季节使用()
组合,然后在下面的路径中引用$1
。
1http://example.com/shirt/winter
变成:
1http://example.com/results.php?item=shirt&season=winter
这也带来了所需的效果。
示例1C:匹配字符集
但是,我们也想指定任何类型的项目,而不仅仅是/shirt
的URL。
- 写一个 regular 表达式 匹配所有字符。 支架表达式
[]
匹配其内部的任何字符,而 `+' 匹配支架 - 组合匹配的任何字符的数量,并将其参考为
$2
作为文件中的第二个变量
1[secondary_label /var/www/html/.htaccess]
2RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2
上面的将转换,例如:
1http://example.com/pants/summer
二:
1http://example.com/results.php?item=pants&season=summer
例1D:通过查询字符串
使用上面的例子,假设我们想重定向 http://example.com/pants/summer
,但会通过一个额外的查询字符串 ?page=2
。
1http://example.com/pants/summer?page=2
地图为:
1http://example.com/results.php?item=pants&season=summer&page=2
如果您试图使用当前设置访问上面的 URL,您会发现查询字符串 page=2
丢失. 此问题可以轻松地通过额外的 QSA
标志来解决。
1[secondary_label /var/www/html/.htaccess]
2RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]
例子二:用逻辑添加条件
RewriteCond
允许我们将条件添加到我们的重写规则中,所有RewriteCond
都遵循以下格式:
1RewriteCond TestString Condition [Flags]
- RewriteCond:指定
RewriteCond
指令 - TestString:对 进行测试的字符串 * 条件:与 匹配的模式 * 旗帜:可能改变条件的可选参数
如果一个RewriteCond
评估为 true,将考虑接下来的RewriteRule
。
** 示例 2A:默认页面**
在想象中的管理面板中,我们可能希望将所有错误的URL重定向到主页,而不是用404打招呼用户。
1[secondary_label /var/www/html/.htaccess]
2RewriteCond %{REQUEST_FILENAME} !-f
3RewriteRule ^admin/(.*)$ /admin/home
这将重定向某些东西,如/admin/blargh
到/admin/home
。
与上面的:
%{REQUEST_FILENAME}
是要检查的字符串!-f
使用了!
不是文件名操作员RewriteRule
重定向所有请求返回/admin/home
请注意,在语法上和技术上更正确的方法是定义404错误文件
。
1[secondary_label /var/www/html/.htaccess]
2ErrorDocument 404 /error.html
** 示例 2B:IP访问限制**
虽然这也可以通过其他方法实现,但可以使用RewriteCond
来限制访问一个 IP 地址或一组 IP 地址。
此示例阻止了来自任何地方的流量 ** 除了** 12.34.56.789。
1[secondary_label /var/www/html/.htaccess]
2RewriteCond %{REMOTE_ADDR} !^(12\.34\.56\.789)$
3RewriteRule (.*) - [F,L]
这个例子仅仅是否定了(旧 mod_rewrite 文章中的示例 3 )( https://andsky.com/tech/tutorials/how-to-set-up-mod_rewrite-page-2)的全部陈述是如果地址是 _not_ 12.34.56.789,请不要允许访问
。
简而言之:
%{REMOTE_ADDR}
是地址字符串!^(12\.34\.56\.789)$
逃脱了所有.
周期,并且使用!
否定了 IP 地址。
如果您更喜欢 block 12.34.56.789,请使用以下内容:
1[secondary_label /var/www/html/.htaccess]
2RewriteCond %{REMOTE_ADDR} ^(12\.34\.56\.789)$
3RewriteRule (.*) - [F,L]
您可以找到更多重写规则,以及如何防止热链接,在原文的 部分 1和 部分 2。
结论
mod_rewrite
可以有效地使用,以确保人类可读的URL。.htaccess 文件本身比仅仅这个模块有更多的用途,但是,应该注意到许多其他 Apache 模块可能会安装以扩展其功能。
还有其他资源详细介绍了mod_rewrite
的功能:
「mod_rewrite」是网络应用程序安全的关键模块,但有时会导致重定向循环或无处不在的、模糊的「500 forbidden」错误。
重写规则是用常规表达式写的,要成为专家,请参考此教程(https://andsky.com/tech/tutorials/an-introduction-to-regular-expressions)。
要快速分析您的常规表达模式,这里有一个在线调试程序(https://regex101.com/),可以提供即时反馈和您常规表达模式的实时解释。