常用基础 - URL重写

  • 作者:KK

  • 发表日期:2017.3.29


有什么用

平时收到/a/b.html的时候就会找a目录下的b.html显示出来,使用URL重写可以实现在收到/a/b.html的时候调用q.php这样跟请求地址不对应的脚本来处理这个地址的请求并发回响应数据。


前提条件

  1. 配置文件加载了mod_rewrite模块,就是大概这样:

    LoadModule rewrite_module modules/mod_rewrite.so
    

  2. 虚拟主机的AllowOverride的值不能是None,必须改成AllowOverride All才能允许重写。


尝试

在web目录下建立一个.htaccess文件,里面写上这样的内容:

RewriteEngine on	#开启URL重写RL重写

#用RewriteRule定义一条重写规则,规则好容易阅读我就不解释了
RewriteRule a/b.html q.php

然后访问/a/b.html就会显示q.php,同时浏览器地址上依然会显示/a/b.html

并且/a/b.html?xx=11&yy=22这样带有GET参数的话也能重定向到q.php,因为Rewrite匹配的只是网址上的pathinfo部分,不是整个URL。

其中上面还带有#号开头的注释,其实.htaccess的配置书写和httpd.conf是一样的,都是指令+参数,只是这里并不支持全部指令,具体要看支持哪些指令,以后要深入学习“作用域”才好说,其实也蛮多指令能在这里用的哦。


隐藏index.php

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php

最后RewriteRule重写的就是将任意请求地址都重定向到index.php。

可是前面还有两个RewriteCond,其实它的含义是说:如果请求的地址指向的不是一个文件和目录,那就重定向给index.php,所以如果有/xx.php这个文件,又访问/xx.php这个地址,就不会重定向到index.php了。


在服务端语言里获取请求相关信息

比如我们要判断请求地址是a/b.html还是xx/yy.html,可以在index.php里echo $_SERVER['REQUEST_URI'];来取得。

而就算地址是/a/b.html?xx=11&yy=22也能通过$_GET数组取得相关参数。


使用正则表达式重定向

这个现在已经比较少用,更多是交给PHP或者JAVA这些服务端编程语言去重定向了

看以下rewrite配置:

RewriteEngine on
RewriteRule news/\d+\.html index.php

news/\d+\.html这其实包含了正则表示符,这里就不介绍正则表达式了。

如此一来访问/news/111.html/news/222.html的时候都会调用index.php,但其它网址就不会重定向给index.php。


编程语言获取正则上的参数

如果像上面那样要index.php获取新闻的ID,那只能从$_SERVER['REQUEST_URI']里用正则匹配了,这是比较辛苦麻烦的事。

其实可以简单点,把重写规则写成RewriteRule news/(\d+)\.html index.php?id=$1这样index.php访问$_GET['id']就能得到新闻ID了。


防盗链

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://xxx.com [NC] 
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .*\.(jpe?g|gif|bmp|png)$ nohotlink.png [L]

就是只允许来源(REFERER)为空、或者为xxx.com的请求获取图片,否则全部都返回nohotlink.png这张图片。

部署这个规则后可以在另一个站点下(比如qqq.com)添加一个<img src="http://xxx.com/111.jpg"/>这样,请求过去时报头的REFERER是qqq.com,而不是xxx.com,于是就导致对方返回了nohotlinkg.png。


子目录也可以放.htaccess

其实.htaccess这个文件不只是能部署在web根目录下的,也能部署在子目录下,比如在/a目录下放.htaccess,内容是:

RewriteEngine on
RewriteRule 333.html /index.php

则访问/a/333.html的时候才会重写到/index.php,注意是重写到web根目录下的index.php,如果改成RewriteRule 333.html index.php就是重写到当前目录下,就是/a/index.php。