我将.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]
PHP|sql|PHP3|PHP4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
order allow,deny
deny from all
第三个也是最后一个.htaccess文件位于名为“small”的上传文件夹的子目录中:
RewriteEngine Off
现在我在/ etc / Nginx中创建了一个名为includes的文件夹,并使用这些重写规则制作了3个单独的.access文件:
对于位于文档根目录中的第一个.htaccess文件,我在/ etc / Nginx / includes中创建了一个名为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 /包含了一个名为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 /中创建了一个包含名称small.access的文件.该文件的内容如下:
# Nginx configuration
location /upload/small {
}
在服务器块配置文件中,我有:
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;
}
现在使用此配置尝试网站时,我收到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错误之外根本无法正常工作.谁能帮我这个?我看不出这里有什么问题.
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读取配置文件时,它会对3种类型的位置块进行排序:
>确切的位置块,例如location = / upload {}
>前缀位置块,例如位置/上传{}
>包含正则表达式的位置块location~ / upload {}
一旦请求到达Nginx,位置选择过程如下:
>如果找到与URI匹配的确切位置块,Nginx将停止搜索其他位置块并提供此请求.
>如果没有,Nginx将搜索最长匹配的前缀位置块,并在进入下一步之前记住它.
>然后Nginx按顺序检查包含正则表达式的位置块.第一个匹配的将用于提供请求.
>如果在上一步中未找到任何内容,则Nginx将使用步骤2的前缀位置块来提供请求.如果没有发现任何事情可能发生,但它是偏离主题的.
因此,在您的情况下,匹配.PHP扩展名的位置块优先于匹配URI的/ upload部分的位置块.
使用^〜你可以告诉Nginx改变他在第2步的行为,这样它就会立即使用匹配的前缀位置,绕过正则表达式位置查找.所以你有2个解决方案:
解决方案1:
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;
}
相同的服务器块
解决方案2:
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文件处理的位置,你当前的配置将不会导致任何事情:检查Nginx fastcgi module.然后你需要在root.access文件中更改你的重写规则,这样它们就不会被解析在当前位置上下文中(即创建一个唯一的回退位置并将更改中断更改为最后一次,以告知Nginx在重写后再次运行位置选择过程).