如何在Debian 9上使用mod_rewrite为Apache重写URL

不使用Debian 9?选择其他版本:

介绍

Apache的mod_rewrite模块允许您以更干净的方式重写URL,将人类可读的路径转换为代码友好的查询字符串。它还允许您根据条件重写URL。

使用.htaccess文件可以创建和应用重写规则,而无需访问服务器配置文件。通过将.htaccess文件放在网站的根目录中,您可以基于每个站点或每个目录管理重写。

在本教程中,您将启用mod_rewrite并使用.htaccess文件来创建基本URL重定向,然后探索几个高级用例。

先决条件

要学习本教程,您需要:

第1步 - 启用mod_rewrite

为了让Apache了解重写规则,我们首先需要激活mod_rewrite。它已经安装,但在默认的Apache安装上被禁用。使用该a2enmod命令启用模块:

sudo a2enmod rewrite

这将激活模块或提醒您模块已启用。要使这些更改生效,请重新启动Apache:

sudo systemctl restart apache2

mod_rewrite现已完全启用。在下一步中,我们将设置一个.htaccess文件,我们将用它来定义重定向的重写规则。

第2步 - 设置.htaccess

一个.htaccess文件,允许我们修改我们的重写规则,而无需访问服务器配置文件。因此,.htaccess对Web应用程序的安全性至关重要。文件名之前的句点可确保隐藏文件。

注意:任何放在.htaccess文件中的规则,您也可以将他们直接放入服务器配置文件中。实际上,官方Apache文档建议使用服务器配置文件,而不是使用.htaccess,因为服务器配置文件的处理时间更快。

但是,在这个简单的例子中,性能提升可以忽略不计。此外,在.htaccess中设置规则很方便,尤其是在同一服务器上有多个网站。它不需要重新启动服务器以使更改生效,也不需要root权限来编辑规则,简化维护以及使用非特权帐户进行更改的过程。像Wordpress和Joomla这样的流行开源软件是依赖.htaccess文件来根据需要进行修改和附加规则。

在开始使用.htaccess文件之前,您需要设置并保护更多设置。

默认情况下,Apache禁止使用.htaccess文件来应用重写规则,因此首先需要允许更改文件。使用nano或其他您喜欢的文本编辑器打开默认的Apache配置文件:

sudo nano /etc/apache2/sites-available/000-default.conf

在该文件中,您将在第一行找到一个<VirtualHost *:80>块。在该块的内部,添加以下新块,以使您的配置文件如下所示。确保所有块都正确缩进。

<VirtualHost *:80>
    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
​
    . . .
</VirtualHost>

保存并关闭文件。

检查您的配置:

sudo apache2ctl configtest

如果没有错误,请重新启动Apache以使更改生效:

sudo systemctl restart apache2

现在,在Web根目录中创建一个.htaccess文件:

sudo nano /var/www/html/.htaccess

在新文件的顶部添加此行以激活重写引擎。

RewriteEngine on

保存文件并退出。

您现在拥有一个可用于管理Web应用程序路由规则的.htaccess操作文件。在下一步中,我们将创建示例网站文件,我们将使用它们来演示重写规则。

第3步 - 配置URL重写

在这里,我们将设置一个基本的URL重写,将漂亮的URL转换为实际的页面路径。具体来说,我们将允许用户访问http://your_server_ip/about,并显示一个名为about.html的页面。

首先创建一个在Web根目录中命名为about.html的文件:

sudo nano /var/www/html/about.html

将以下HTML代码复制到该文件中,然后保存并关闭它。

<html>
    <head>
        <title>About Us</title>
    </head>
    <body>
        <h1>About Us</h1>
    </body>
</html>

您可以访问此http://your_server_ip/about.html页面,但请注意,如果您尝试访问http://your_server_ip/about,则会看到404 Not Found错误。为了要使用/about访问页面,我们将创建一个重写规则。

全部RewriteRules遵循以下格式:

RewriteRule pattern substitution [flags]
  • RewriteRule 表明指令。
  • pattern是一个正则表达式,匹配URL中所需的字符串,这是查看器在浏览器中键入的内容。
  • substitution 是实际URL的路径,即Apache服务的文件的路径。
  • flags 是可以修改规则工作方式的可选参数。

让我们创建我们的URL重写规则。打开.htaccess文件:

sudo nano /var/www/html/.htaccess

在第一行之后,添加以下 RewriteRule 并保存文件:

RewriteEngine on
RewriteRule ^about$ about.html [NC]

在这种情况下,^about$是模式而about.html是替换,[NC]是标志。我们的示例使用了一些具有特殊含义的字符:

  • ^表示your_server_ip/之后URL的开头。
  • $ 表示URL的结尾。
  • about 匹配字符串“about”。
  • about.html 是用户访问的实际文件。
  • [NC] 是一个使规则不区分大小写的标志。

您现在可以在浏览器中访问http://your_server_ip/about``about.html。实际上,根据上面显示的规则,以下URL也将指向:

  • http://your_server_ip/about,因为规则定义。
  • http://your_server_ip/About,因为规则不区分大小写。
  • http://your_server_ip/about.html,因为原始文件名将始终有效。

但是,以下内容不起作用:

  • http://your_server_ip/about/,因为规则明确规定about之后可能没有任何内容,因为$角色出现在about之后。
  • http://your_server_ip/contact,因为它与规则中的about字符串不匹配。

您现在拥有一个带有基本规则的.htaccess操作文件,您可以根据自己的需要进行修改和扩展。在以下部分中,我们将展示常用指令的另外两个示例。

示例1 - 使用RewriteRule简化查询字符串

Web应用程序通常使用查询字符串,这些字符串在地址后使用问号(?)附加到URL 。使用&符号(&)分隔单独的参数。查询字符串可用于在各个应用程序页面之间传递附加数据。

例如,用PHP编写的搜索结果页面可能使用类似 http://example.com/results.php?item=shirt&season=summer的URL。在此示例中,将两个附加参数传递给虚构的result.php应用程序脚本:值为shirtitem应用程序脚本和值为summerseason应用程序脚本。应用程序可以使用查询字符串信息为访问者构建正确的页面。

Apache重写规则通常用于将上述示例中的长而不愉快的链接简化为友好的URL,这些URL更易于在视觉上进行打字和解释。在这个例子中,我们想将上面的链接简化为http://example.com/shirt/summer。在shirtsummer参数值仍然在地址,但没有查询字符串和脚本名称。

以下是实现此目的的一条规则:

RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer [QSA]

shirt/summer是明确匹配在请求的地址中的并且Apache被告知将另外服务于results.php?item=shirt&season=summer

[QSA]标志在重写规则常用。它们告诉Apache将任何其他查询字符串附加到提供的URL,因此如果访问者输入http://example.com/shirt/summer?page=2,服务器将以results.php?item=shirt&season=summer&page=2响应。没有它,额外的查询字符串将被丢弃。

虽然此方法可实现所需效果,但项目名称和季节都硬编码到规则中。这意味着该规则不适用于任何其他items,比如如pants,或seasons,如winter

为了使规则更通用,我们可以使用正则表达式匹配原始地址的各个部分,并在替换模式中使用这些部分。修改后的规则将如下所示:

RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]

括号中的第一正则表达式组包含字母数字字符和数字等比如shirtpants的字符串匹配并保存匹配片段作为变量$1。括号中的第二正则表达式组完全匹配summerwinterfall,或spring,并且类似地节省了匹配片段作为$2

然后将匹配的片段用于生成在itemseason变量中的URL ,而不是之前使用的硬编码shirtsummer值。

例如,上面将把http://example.com/pants/summer转换为http://example.com/results.php?item=pants&season=summer。此示例也是未来证明,允许使用单个规则正确地重写多个项目和季节。

示例2 - 使用RewriteConds添加逻辑条件

重写规则不一定总是逐个评估,没有任何限制。该RewriteCond指令允许我们为重写规则添加条件,以控制何时处理规则。全部RewriteConds遵守以下格式:

RewriteCond TestString Condition [Flags]
  • RewriteCond指定RewriteCond指令。
  • TestString 是要测试的字符串。
  • Condition 是匹配的模式或条件。
  • Flags 是可选参数,可以修改条件和评估规则。

如果RewriteCond评估为true,则考虑下一个RewriteRule。如果没有,则该规则将被丢弃。可以一个接一个地使用多个RewriteConds,但是对于要考虑的下一个规则,所有必须评估为真。

例如,假设您希望将所有请求重定向到您站点上不存在的文件或目录,并将其重定向到主页,而不是显示标准的404 Not Found错误页面。这可以通过以下条件规则来实现:

将所有请求重定向到不存在的文件和目录到主页

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /

根据上述:

  • %{REQUEST_FILENAME}是要检查的字符串。在这种情况下,它是请求的文件名,它是可用于每个请求的系统变量。
  • -f是一个内置条件,它验证所请求的名称是否存在于磁盘上并且是一个文件。这!是一个否定运算符。合并后,仅当指定的名称不存在或不是文件时才计算!-f结果为true。
  • 同样,仅当指定的名称不存在或不是目录时,计算!-d结果为true。

在最终线上的RewriteRule只有当为请求不存在的文件或目录时才生效。RewriteRule本身非常简单,并将每个请求重定向到/网站根目录。

结论

mod_rewrite允许您创建人类可读的URL。在本教程中,您学习了如何使用该RewriteRule指令重定向URL,包括具有查询字符串的URL。您还学习了如何使用该RewriteCond指令有条件地重定向URL 。

如果您想了解更多信息mod_rewrite,请查看Apache的mod_rewrite简介Apache的mod_rewrite官方文档

更多Debian教程请前往腾讯云+社区学习更多知识。


参考文献:《How To Rewrite URLs with mod_rewrite for Apache on Debian 9》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

深入讲解GCC和Make的区别(有涉及makefile文件哟!!!)

gcc是编译器 而make不是 make是依赖于Makefile来编译多个源文件的工具 在Makefile里同样是用gcc(或者别的编译器)来编译程序.

1K3
来自专栏塔奇克马敲代码

Windows环境下的RTKPlot_Qt版本编译时遇到的问题和解决方法

1645
来自专栏AndroidTv

继续封装个 Volley 组件前言二次封装Github地址

那么,今天继续再来封装一个网络组件,基于 volley 的二次封装,目的也是为了简化外部使用,以及新项目可快速接入使用。

972
来自专栏数据之美

shell 学习笔记(19)

声明:转载需署名出处,严禁用于商业用途! 1801.关于 nohup 后台运行的问题: nohup就是拒绝hup信号,没什么其他用途, 如...

2295
来自专栏aoho求索

基于redis的分布式锁实现

关于分布式锁 很久之前有讲过并发编程中的锁并发编程的锁机制:synchronized和lock。在单进程的系统中,当存在多个线程可以同时改变某个变量时,就需要...

4358
来自专栏orientlu

vim 插件使用记录

指令 效果 C_ ] 直接跳转到定义处 C_ t 往回跳转一次(先输入数字再C_t,可以一次回跳多个) : tags 查看跳转list ...

922
来自专栏Java帮帮-微信公众号-技术文章全总结

集群间如何实现session共享【面试+工作】

3K8
来自专栏阿杜的世界

Serviceability Agent介绍简单介绍安装使用模式入门示例SA的其他工具参考资料

构建高性能的Java应用过程中,必然会遇到各种各样的问题,像CPU飙高、内存泄漏、应用奔溃,以及其他疑难杂症,这时可以使用Serviceability Agen...

1873
来自专栏后端技术探索

nginx,memcached,redis网络模型总结

nginx采用多进程模型,含一个master进程和多个worker进程,worker进程数目可配置,一般与机器CPU核心数目一致,master进程主要职责是:接...

2012
来自专栏祥子的故事

python | os包常用命令介绍

3825

扫码关注云+社区

领取腾讯云代金券