我试图使用java.net.HttpURLConnection在Java中“欺骗”Firefox HTTP POST请求。 我使用Wireshark来检查发送的HTTP头,所以我(希望)有可靠的信息来源,为什么Java结果与理想情况不符(使用Firefox)。
我已将所有标题字段完全设置为Firefox通过HTTP发送的值,并注意到标题字段的顺序不一样。 Firefox的输出如下:
POST ...
**Host**
User-Agent
Accept
Accept-Language
Accept-Encoding
Referer
Connection
Content-Type
Content-Length
当我让wireshark在Java中点击我的实现时,它给了我一个稍微不同的字段序列:
POST...
**User-Agent**
Accept
Accept-Language
Accept-Encoding
Referer
Content-Type
Host
Connection
Content-Length
所以基本上,我有所有的字段,只是以不同的顺序。
我还注意到Host字段的发送值不同:
www.thewebsite.com
(Firefox)< ---> thewebsite.com
(Java HttpURLConnection),虽然我使用“www。”将字符串传递给httpUrlConnection.setRequestProperty
。
我还没有分析过Wireshark的字节输出,但是我知道服务器在我的响应的标题字段中没有返回相同的Location
。
我的问题是:
(1)是否可以控制请求中标题字段的顺序,如果是,是否可以使用HttpURLConnection
?如果没有,是否可以使用Java直接控制HTTP头中的字节? [我不拥有服务器,所以我唯一的希望让POST方法正常工作是通过我的应用假冒Firefox,服务器并不是真的很冗长,我的唯一信息是:Apache with PHP]
(2)有没有办法解决上面描述的setRequestProperty()问题(“www”)?
(3)还有什么重要的? (我需要关注底层,TCP ......?)
感谢您提出任何意见。
PS。我试图模拟没有发送cookie的情况,这样我就可以忽略这种效果。
答案 0 :(得分:5)
首先,标题的顺序无关紧要。
其次,为了手动覆盖host
标题,您需要在代码中设置sun.net.http.allowRestrictedHeaders=true
System.setProperty("sun.net.http.allowRestrictedHeaders", "true")
或在JVM开始
-Dsun.net.http.allowRestrictedHeaders=true
这是Oracle不久前提出的一项安全预防措施。那是因为根据RFC
Host request-header字段指定Internet主机和端口 请求的资源编号,从原始编号获得 用户或引用资源(通常是HTTP URL)提供的URI。
答案 1 :(得分:2)
标题顺序并不重要。服务器获得的标头也是无序的。并且您无法控制httpUrlConnection标头顺序。但是,如果您编写自己的TCP客户端,则可以控制标题顺序。像:
clientSocket = new Socket(serverHost,serverPort);
OutputStream os = clientSocket.getOutputStream();
String send = "GET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\nGET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\n";
os.write(send.getBytes());
MarcelStör在第一个答案中回答了第二个问题。 一个
答案 2 :(得分:0)
我很幸运使用Apache Http Components,我的猜测是" Host"标题缺少" www。"差异化,可以使用Apache的HttpPost
:
httpPost.setHeader("Host", "www.thewebsite.com");
Wireshark输出证实了我的怀疑。此次,我的HTTP帖子之前的TCP通信看起来不同(客户端--->服务器,服务器--->客户端,客户端--->服务器)而不是(客户端--->服务器,服务器) --->客户端,客户端--->服务器,客户端--->服务器)。
现在我获得了所需的Location
标头值,服务器也在设置cookie。 :)
在大多数情况下,这个问题已得到解决。
实际上我想使用lightweihgt HttpUrlConnection
,因为这是Android Developers博客建议的内容。 System.setProperty("sun.net.http.allowRestrictedHeaders", "true")
如果允许{" www。"在Host
值。