我在将.htaccess文件转换为nginx时遇到了麻烦。 我有3个.htaccess文件。 第一个.htaccess文件位于文档根目录中,如下所示:
Options +FollowSymLinks RewriteEngine On RewriteRule ^img-(.*)\.html img.php?id=$1 [L] RewriteRule ^slide-(.*)\.html slider.php?id=$1 [L] RewriteRule ^page-(.*)\.html page.php?name=$1 [L] RewriteRule ^contact\.html$ contact.php [QSA,L,NC]
第二个.htaccess文件位于一个名为upload的文件夹中:
RewriteEngine On RewriteCond %{HTTP_REFERER} !^http://(.+\.)?foo\.com/ [NC] RewriteCond %{HTTP_REFERER} !^$ RewriteRule .*\.(jpe?g|gif|bmp|png)$ nohotlink.gif [L] <Files ~ "\.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$"> order allow,deny deny from all </Files>
第三个也是最后的.htaccess文件位于名为“small”的上传文件夹的子目录中:
RewriteEngine Off
现在我在/ etc / nginx中创build了一个名为includes的文件夹,并用这些重写规则创build了3个独立的.access文件:
对于位于文档根目录中的第一个.htaccess文件,我在/ etc / nginx / includes中创build了一个名为root.access的文件。 在这个文件中我有:
# nginx configuration location /img { rewrite ^/img-(.*)\.html /img.php?id=$1 break; } location /slide { rewrite ^/slide-(.*)\.html /slider.php?id=$1 break; } location /page { rewrite ^/page-(.*)\.html /page.php?name=$1 break; } location /contact { rewrite ^/contact\.html$ /contact.php break; }
对于位于“upload”文件夹中的第二个文件,我在/ etc / nginx / includes中创build了一个名为upload.access的文件。 该文件包含以下内容:
# nginx configuration location /upload { if ($http_referer !~ "^http://(.+\.)?foo\.com/"){ rewrite .*\.(jpe?g|gif|bmp|png)$ /nohotlink.gif break; } } location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ { deny all; }
对于第三个也是最后一个文件,我在/ etc / nginx / includes names small.access中创build了一个文件。 这个文件的内容如下:
# nginx configuration location /upload/small { }
在服务器块configuration文件中我有:
location / { try_files $uri $uri/ /index.php; include /etc/nginx/includes/root.access; } location /upload { include /etc/nginx/includes/upload.access; } location /upload/small { include /etc/nginx/includes/small.access; }
现在使用此configuration时,尝试站点我收到403错误。 Nginx错误日志报告:
[error] 18156#0: *7 access forbidden by rule, client: 111.**.**.**, server: foo.com, request: "POST /upload.php HTTP/1.1", host: "foo.com", referrer: "http://foo.com/"
现在在Apache下,一切都没有问题。 但我不明白为什么我得到403错误。 我也担心,我所说的改写规则超出了403错误,根本无法正常运作。 谁能帮我这个? 我看不出这里有什么问题。
这是这部分configuration的标准nginx行为:
location /upload { if ($http_referer !~ "^http://(.+\.)?foo\.com/"){ rewrite .*\.(jpe?g|gif|bmp|png)$ /nohotlink.gif break; } location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ { deny all; } }
为什么?
让我来澄清位置如何工作:当nginx读取configuration文件时,它将按3种types对位置块进行sorting:
location = /upload { } location /upload { } location ~ /upload { } 一旦请求到达nginx,位置select过程如下:
所以在你的情况下,匹配.php扩展名的位置块优先于匹配URI的/upload部分的位置块。
编辑 :澄清解决scheme,添加替代解决scheme。
使用^~你可以告诉nginx改变他的行为,所以它会立即使用匹配的前缀位置,绕过正则expression式位置查找。 所以你有2个解决scheme:
解决scheme1 :
upload.access:
if ($http_referer !~ '^http://(.+\.)?foo\.com/') { rewrite '.*\.(jpe?g|gif|bmp|png)$' '/upload/nohotlink.gif' break; } if ($uri ~ '\.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$') { return 403; }
相同的服务器块
解决scheme2 :
upload.access:
if ($http_referer !~ '^http://(.+\.)?foo\.com/') { rewrite '.*\.(jpe?g|gif|bmp|png)$' '/upload/nohotlink.gif' break; } location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ { deny all; }
服务器块:
location ^~ /upload { include /etc/nginx/includes/upload.access; }
现在,如果您不设置位置来转发php文件处理,您当前的configuration将不会导致任何事情:检查nginx fastcgi模块 。 然后你将需要在root.access文件中改变你的重写规则,这样它们在当前位置上下文中就不会被parsing(例如,创build一个唯一的备用位置,并改变last的位置以告诉nginx在重写之后再次运行位置select过程) 。