现代化的 Typecho Nginx 规则书写
现在的中文互联网信息真的是一言难尽,如屎海淘金,不管你如何好学肯上进,搜索问题得到的答案通常都是反复转载且过时甚至是错误的。
好比搜索关于 Typecho 的 Nginx 规则,大概率会得到如下答案:
#伪静态
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-e $request_filename){
rewrite (.*) /index.php;
}
# 安全设置
rewrite /(var|usr)(.+ph*)$ /index.php;
rewrite /(config.inc.php|.htaccess)$ /index.php last;
然而对于现在你手上的 Nginx 来说:
if指令是低效的:Nginx 官方文档多次强调应避免使用if来进行路由判断,它的执行顺序和作用域有时会违反直觉,效率也低于try_files。- 丢失了请求参数:
rewrite (.*) /index.php; 这句规则的含义是:“如果请求的文件或目录不存在,就把请求的URL重写为/index.php”。问题在于,它把所有不匹配的URL都粗暴地指向了/index.php,却丢掉了原始的请求路径和查询参数。 rewrite /(var|usr)(.+ph*)$ /index.php;这条规则意图不明且有风险。Typecho 的核心文件就存放在 usr 目录,这条规则可能会无意中拦截正常的后台请求。rewrite /(config.inc.php|.htaccess)$ /index.php last;这是一种过时且不安全的写法。对于敏感文件,我们应该直接返回 403 Forbidden 或 404 Not Found,而不是把它重写到 index.php。使用 location 块来处理是更标准、更安全的方式。
下面是一些建议的写法。
核心的 URL 重写规则 (现代化、高效且正确)解决 404 问题
location / { # 尝试文件 -> 尝试目录 -> 交给 index.php 处理 try_files $uri $uri/ /index.php?$query_string;; } # try_files 指令会按顺序检查: # $uri - 是否存在与请求URI完全匹配的文件 (例如 /style.css) # $uri/ - 是否存在与请求URI完全匹配的目录 (例如 /admin/) # /index.php?$args - 如果前两者都找不到,则将请求内部转发给 index.php,并附加原始的请求参数($args)统一的安全设置 (更清晰、更标准)
# 直接禁止访问所有PHP文件在非后台入口的敏感目录 location ~* /(app|content|lib)/.*\.(php|php5)$ { deny all; } # 禁止访问特定的配置文件和开发文件 location ~* /(composer\.json|composer\.lock|\.git|\.env|\.htaccess) { deny all; } # 对Typecho根目录的配置文件进行精确匹配和禁止,性能更高 location = /config.inc.php { deny all; }静态资源处理与优化
# 为所有静态资源设置浏览器缓存,并添加CORS头 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { # 允许跨域,方便CDN或API调用字体 add_header Access-Control-Allow-Origin "*"; # 设置浏览器缓存时间为1个月 expires 1M; # 关闭此location的访问日志,减少IO消耗 access_log off; }图片 404 优化
location ~* \.(jpe?g|png|gif|webp)$ { log_not_found off; try_files $uri /content/images/system/default/404.gif; # 使用 try_files 来更优雅地实现 # 如果原始图片($uri)存在,就返回它;如果不存在,就返回默认的404图片 }
现在,你可以尝试着去改改你那些舅姥爷写的 Nginx 规则了,当然记得先备份,先备份,先备份。
改完了别忘了 nginx -t 没问题 nginx -s reload 重新上膛。
OVER!