本周Apache Rewrite学习小结

今天终于把Apache的.htaccess的Rewrite给搞到差不多了,基本上可以解决四个问题:

  1. 基本的域名规范化
  2. 子目录→子域名重定向问题
  3. 禁止通过路径访问子站点的基本措施
  4. 基本的PHPWind(7.5)伪静态支持

我在这里将这些经验记下来,不管怎么说这也是我辛苦了四天摸索出来的经验,也许哪位朋友刚好会需要。

假想场景

举例说,有PHPWind站点a.com,其主要内容在/phpwind目录下,在/wordpress目录下还有另一个子站点(某版主的个人博客?),域名绑定为b.com。

a.com (www.a.com)
├/phpwind (bbs.a.com)
└/wordpress (www.b.com)

如果不做设置,那么想要访问网站a,可以通过http://(www.)a.com/phpwind进入;如果想要进入某版主的博客,则既可以通过http://(www.)b.com,又可以通过http://(www.)a.com/wordpress进入。

这么一来存在3个问题:

  1. 一个典型的域名规范化问题:既可以通过有www的网址进入,又可以通过没有www的网址进入,不利于SEO。
  2. 一个可能让不少人觉得不爽的问题:a.com下面其实是空的,真正的站点地址后面拖了个长长的/phpwind。
  3. 一个可能触动一些人隐私神经的问题:可以通过a.com/wordpress进入站点b.com,很容易看出两者是在同一台主机上,这可能让这两个站点的所有者感到没有安全感。

注意事项:

许多人也许首先会尝试照着步骤一步一步照猫画虎,结果却发现卡在其中某一步无法继续了,非常沮丧地放弃了,而事实上在文章的最后其实写有备注,解决这些问题,因此为了尽可能避免这种情况,我将备注写在这里。希望尽早进入正文的朋友可以先跳过这里。

  1. 非常重要:如果.htaccess文件同时存在于子目录与根目录下,当访问子目录时,根目录下的.htaccess会被!!忽略!!(不是“优先”,而是根目录下的彻底无效。)由于一些程序为实现一些功能自带有.htaccess(如WordPress),因此许多人会因为没有注意到这一点而绕圈。

  2. 重要:尽可能避免在子目录中使用.htaccess,如果无法避免,始终记得!RewriteRule中的匹配条件是针对根目录的,包含子目录!哪怕.htaccess文件是放在/wordpress目录下,用的www.b.com地址访问,RewriteCond行中写的是^www.b.com$,在RewriteRule行中还是必须写^wordpress/(.*)$而不是^(.*)$。

    在个别情况下,请求地址可能会包括进整个站点的根地址,可以用类似如下的方法解决:


    RewriteCond %{HTTP_HOST} ^www.b.com$ [NC]
    RewriteRule ^(.*)wordpress/(.*)$ http://www.b.com/$2 [R=301,L]

    这样一来,由于第一个(.*)被忽略掉了,只使用了$2而没有$1,哪怕前面多了再多乱七八糟的东西,也可以被过滤掉,除非RP很好刚好前面也有个目录叫wordpress……

  3. 网上很多教程里看到的转义符“”,有的时候并不是必要的,甚至可能引发问题,这个需要针对不不同的服务器版本自行尝试了。

  4. 在RewriteRule中使用了[R]参数后,浏览器的地址栏会被改写,如果不用则不会改写,如果要加上[R],千万记得在目标地址中写上完整的头(http://www.a.com/)。

  5. 不同的服务器版本,加不加[R]的情况下,目标规则中对于特殊字符的转码要求是不同的,比如“?”字符,在PHP论坛静态化时是不可或缺的,如果发现直接输入“?”报错,试试看%3F。

一、域名规范化

想要将b.com直接转到www.b.com,不管是搜索引擎还是用户,可以试试这么写:

RewriteCond %{HTTP_HOST} ^b.com$ [NC]
RewriteRule ^wordpress/(.*)$ http://www.b.com/$1 [R=301,L]

别忘了子目录啊!

二、子域名重定向

想要将http://www.a.com/phpwind统一到http://bbs.a.com?

RewriteCond %{HTTP_HOST} ^www.a.com$ [NC]
RewriteRule ^phpwind(.*)$ http://bbs.a.com$1 [R=301,L]

如果外面还有更多层子目录也别忘记啊!

三、禁止通过子目录访问

不想让用户通过a.com/wordpress访问到b.com?

一种比较“补丁”式的方法是:

RewriteCond %{HTTP_HOST} ^www.a.com$ [NC]
RewriteRule ^wordpress(.*)$ "" [F,L]

使用了[F]参数,强制服务器返回一个403 Forbidden……

其实还有一种更绝的方法,绑定域名的时候就将a.com绑定成子目录/phpwind的域名……至于主机域名,随便给个什么乱七八糟的asdf.a.com就行。这样bbs.a.com这个子域名就省了,把www.a.com/phpwind跳转到bbs.a.com也可以免了。之后在.htaccess里这么写:

RewriteCond %{HTTP_HOST} ^asdf.a.com$ [NC]
RewriteRule ^(.*)$ "" [F,L]

这种情况下,哪怕别人有意无意进入了asdf.a.com,不管后面是什么文件或者目录,都会看到一个403 Forbidden。有一种情况例外:这人输入了asdf.a.com/123 AND 刚好站点中有/123这个目录 AND /123目录中刚好有.htaccess AND 这个.htaccess中没有做同样的配置。所以说,如果每个文件夹都要弄个.htaccess会带来一些麻烦,尽量统一管理吧。

PHPWind 7.5的伪静态

PHPWind的后台伪静态设置页面给了一个代码:

RewriteRule ^(.*)-htm-(.*)$ $1.php?$2

但是这个设置其实是不够的,如果发现这样还是失败,可以尝试这么写:

RewriteCond %{HTTP_HOST} ^bbs.a.com$ [NC]
RewriteRule ^phpwind/(.*)-htm-(.*)-(.*).html$ http://bbs.a.org/$1.php?$2=$3 [L]

如果想要更改地址栏显示,可以加上[R],这样用户们看起来就好像没有伪静态一样。

注意:这个情况非常容易遭遇上文“注意事项”中提到的2、3、4、5点情况……

小结

嗯,今天的文章就写到这里。对于Web服务器配置这种深奥的东西,我自己也只是刚刚入门四天,还在摸索阶段,以上文章只是将我个人的经历做了总结,希望能够帮到和我一样正陷入困难的朋友。其中难免还会有一些错误(毕竟是菜鸟),还请多多指点,感激不尽~~