我有Django在端口8000上运行,Apache在80端口上运行。我在apache中配置了以下重写规则以重定向到django:
RewriteRule ^/?checkout/ http://%{HTTP_HOST}:8000/checkout/ [L,QSA]
如果在浏览器中打开一个url,它可以很好地工作并完美地重定向。在
但是,外部客户机(在没有apache的情况下直接连接到django时工作良好)总是导致django服务器上出现错误的请求语法错误。这是Django日志中的片段。看起来Apache会自动将那些“内容长度”的内容附加到查询中,为什么?在
^{pr2}$
dr:这是由“外部客户机”中的一个错误引起的。它是一个设计糟糕的HTTP客户机,应该避免,因为它不仅会导致此错误,还可能为安全漏洞利用开辟途径。在
为了了解发生了什么,你需要反向工作。在
首先,让我们从Django内置服务器的日志行开始:
“代码400”是指HTTP状态代码400。这意味着实际的HTTP request结构不好,无法理解。幸运的是,Django记录了错误的输入,这样我们就可以分析它了。在
既然我们了解了问题的本质,我们将删除不相关的日志绒毛和长签名,以便更深入地了解实际请求:
^{2}$这里我们看到一个无效的HTTP请求的第一行。在
从RFC2616 Section 5.1:
在无效请求中,我们可以确定HTTP动词}的版本结尾在那里,所以这些不是问题所在。中间部分,即URL,如下所示:
GET
在那里,而{在发送到服务器之前,URL中的空格通常被}替换。如您所见,这里不是这种情况,这是无效请求的原因。一个好的HTTP客户机永远不会这样做,因为它会自动转义URL。这是一个危险信号,表明您使用的“外部客户”质量低劣。
+
或{注意,这个空间出现在一些看起来很奇怪的区域旁边。在
如果您查看RFC2616 Section 14.13,您将看到
Content-Length
实际上是HTTP1.1头的名称。这也是Connection
,和Content-Type
的情况。在它显然不属于那里,那么为什么它与URL连接?在
从这里我只能猜测,因为我不能访问你的代码。不过,我想我对发生的事情有一个很好的了解。在
让我们先了解一下HTTP头的性质。我们将发送一个原始请求来模拟访问“http://google.com”时发生的情况。这将触发Google将我们重定向到“http://www.google.com”。在
原始请求:
原始响应:
哇,谷歌返回了一大堆标题!我们只对前几行感兴趣:
在这里您可以看到
Content-Type
,Content-Length
,以及其他头文件都跟在Location
头之后。实际的顺序通常并不重要,因为HTTP客户机或服务器足够智能,能够理解每一个客户机或服务器的含义。但是,如果去掉Location
头之后的行尾怎么办?在你最终会得到这样的结果:
哦哦。。。如果您是HTTP客户机,您会认为我希望将您重定向到
http://www.google.com/Content-Type: text/html; charset=UTF-8Content-Length: 219
。在这看起来和你的症状一模一样。。。但为什么会这样呢?在
Apache不太可能以这种损坏的形式返回头(除非您自定义了一个插件或其他类似的代码)。在
你的“外部客户”也不太可能在收到邮件后故意删除邮件头中的行尾。在
很可能的情况是,“外部客户机”被编码为将内容之前和
Location:
之后的所有内容解释为URL,然后在某处去除CRLF字符(通常在处理HTTP报头时出于安全原因而这样做,讽刺的是,在本例中错误地处理)。客户端试图用HTTP/1.0而不是HTTP/1.1发送请求,这一事实支持这一点,因为HTTP/1.0客户端通常在功能方面非常有限,并且往往基于其过时的知识做出大量假设。在您的“外部客户机”很可能会将请求行之后的整个头读入字符串,并自动将字符串处理程序读入字符串我剥了CRLF。在
我认为很明显问题出在“外部客户”身上,尽管没有足够的信息来挖掘它。在
我建议您使用不同的客户机或库来完成请求。在
此消息似乎出现在you are using HTTPS url with Django时。您可能还需要在Apache2中配置一个HTTPS配置,这个配置的灵感来自于这个问题,例如:SSL based virtual host with django and mod_wsgi
相关问题 更多 >
编程相关推荐