Nginx重写规则403错误

前端之家收集整理的这篇文章主要介绍了Nginx重写规则403错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我将.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错误之外根本无法正常工作.谁能帮我这个?我看不出这里有什么问题.

最佳答案
这是此部分配置的标准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读取配置文件时,它会对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在重写后再次运行位置选择过程).

猜你在找的Nginx相关文章