外部链接URL编码导致Nginx服务器上的'%3F'和'%3D'



我的服务器出现问题。我有四个到我的动态网页不同网站的入站链接,看起来像这样:

myurl.com/default/Site%3Fid%3D13

它们应该是这样的:

myurl.com/default/Site?id=13

我知道%3F?符号的转义序列,%3D是等号的转义序列。但当我使用这些链接时,我确实得到了错误400。我该怎么办?

这四个链接适用于不同的网站,我想随着时间的推移,会有更多这样的链接。因此,一个解决方案将是完美的。

大约一年前,nginx-ru邮件列表上也提出了一个完全相同的问题:

http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050200.html

最有帮助的回应,由Nginx公司的员工/开发人员,ВалиинБариаийаайицилана:

http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050209.html

Слизафайла。位置。

翻译:

如果请求以这样的形式出现,那么这些不再是参数,而是请求文件的名称。另一件事是,如文档所述,位置匹配是针对规范化的URI执行的。

他建议的解决方案,转化为SO的问题示例,将是:

location /default/Site? {
    rewrite ?(.*)$ /default/Site?$1? last;
}
location = /default/Site {
    [...]
}

以下示例会将所有看起来错误的请求(定义为请求文件名中有?,在请求中编码为%3F)重定向到看起来不太错误的请求,而不管URL如何。

(请注意,正如其他地方正确建议的那样,您一开始就不应该获得这些格式错误的链接,因此,只有在您无法以其他方式更正格式错误的连接,并且您知道此类请求是由有效代理尝试的情况下,才可将其作为最后手段。)

server {
    listen      [::]:80;
    server_name localhost;
    rewrite     ^/([^?]*)?(.*)$    /$1?$2?     permanent;
    location / {
        return  200 "id is $arg_idn";
    }
}

这是一个如何运作的例子—当遇到一个看起来错误的请求时,会用一个301 Moved Permanently响应和一个假定正确的Location响应头进行更正尝试,这将使浏览器自动将请求重新发布到新提供的位置:

opti# curl -6v "http://localhost/default/Site%3Fid%3D13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site%3Fid%3D13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:25 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/default/Site?id=13
< Connection: keep-alive
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.1</center>
</body>
</html>
* Connection #0 to host localhost left intact
* Closing connection #0

请注意,对于外观正确的请求,不会进行任何更正尝试:

opti# curl -6v "http://localhost/default/Site?id=13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site?id=13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:30 GMT
< Content-Type: application/octet-stream
< Content-Length: 9
< Connection: keep-alive
<
id is 13
* Connection #0 to host localhost left intact
* Closing connection #0

URL完全有效。它包含的转义字符就是转义字符。这很好。

这样做的目的是,您实际上可以有一个请求名称(在大多数情况下对应于磁盘上的文件名),它是Site?id=13而不是Site,其余的作为查询字符串。

我认为在文件名中包含字符是不好的做法,这样做是必要的。然而,在URL参数中,这可能是非常必要的。

尽管如此,请求URL是有效的,可能不是你想要的。因此,这建议你应该在任何人一开始就收到错误URL的地方更正错误。

我真的不明白为什么你会得到一个错误400;你应该得到一个错误404。但这取决于你的设置。

也有一些情况,尤其是nginx,主要涉及在多个级别传递整个URL和URL部分(例如反向代理、从URL匹配正则表达式并将其用作变量等),可能会发生此类错误。但要验证并修复它,我们需要了解更多关于您的设置。

相关内容

  • 没有找到相关文章

最新更新