使用Apache的Rewrite解决ThinkPHP入口在Public目录的问题
本文完整阅读约需 7 分钟,如时间较长请考虑收藏后慢慢阅读~
在部署ThinkPHP业务时,我们经常需要将Web服务器根目录指向ThinkPHP源码的
public
目录,因为该目录内有ThinkPHP的启动脚本,即index.php
。但在某些情况下(虚拟主机或Docker甚至Kubernetes等环境下),我们无法直接修改配置文件来将根目录切换到public
。
但如果这个时候刚好使用Apache作为Web服务器,就可以利用其Rewrite配置来轻松解决这一问题。
0x01
上面已经介绍过,我们需要在不修改配置文件的情况下实现让根目录指向public
目录,这就需要使用Apache的一个杀手锏:动态配置。
如果下载过PHP源码(或其他语言源码)的读者,应该对.htaccess
文件不陌生,这就是Apache的动态配置文件,即Hypertext Access,超文本入口。
该文件描述了该目录(包含子目录,除非子目录中有另外的显式配置)下的访问规则,通常包含以下配置:
– 声明错误页
– 重定向(301、302等)
– URL重写
– 密码保护(使用HTTP认证)
– 通过IP地址禁用访客
– 通过来源禁用访客(即反盗链)
– 禁止爬虫(通过UserAgent判断)
– 首页文件
– 新增/修改MIME类别
– 启用服务端内嵌脚本语言(即SSI)
– 启用CGI支持
– 开启/关闭列出目录功能
– 设置服务器语言/时区
– 避免访问框架、密匙等隐藏文件
– 避免静态目录中出现脚本执行漏洞
– 区分媒体文件的下载与播放
– 设置输出编码
– 屏蔽包含特殊字符的请求,增强安全性
……
我们在这里需要使用的就是URL重写这一功能。
0x02
首先我们需要在源码根目录下放置一个.htaccess
文件,设置该文件的拥有者为httpd
(根据你环境的Apache进程所属用户不同,可能有所变化):
touch ./.htaccess
chown -R httpd:httpd ./.htaccess
然后使用你喜欢的编辑器打开该文件,在其中写入如下配置:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/$1?Rewrite [L,QSA]
</IfModule>
再次打开根目录,即发现不需要访问public
子目录也可以实现访问业务。
0x03
功能实现了,但原理还未说明,接下来我来解释一下上文.htaccess
文件的结构与原理:
<IfModule mod_rewrite.c>
RewriteEngine On
...
</IfModule>
这一段不用多说,即检测是否安装mod_rewrite模块,如果安装即可启动URL重写功能。
RewriteBase /
该段的作用是对什么子目录应用伪静态,通常为
/
,但如果是需要针对某个目录(虚拟目录)应用不同的伪静态配置,可以指定为某个虚拟目录,注意要以/
开头,结尾不需要/
。
RewriteCond %{REQUEST_URI} !^/public/
该段的作用是针对非访问
/public
目录的所有URI应用伪静态配置,可以理解为编程语言中if
的作用。
RewriteRule ^(.*)$ public/$1?Rewrite [L,QSA]
该段的作用是对满足以上所有条件的URI应用伪静态规则,这部分的规则极为复杂,具体可参考Apache关于该部分的文档。
事实上.htaccess
文件的格式和httpd.conf
基本一致,因此很多需要限定作用域(例如目录作用域)的配置都可以放在该文件里以实现动态配置。