【问题标题】:Java HttpURLConnection | POST method | Sequence of HTTP header fieldsJava HttpURL 连接 | POST 方法 | HTTP 标头字段的序列
【发布时间】:2013-12-26 22:46:02
【问题描述】:

我正在尝试使用 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 ......?)

感谢任何cmets。

附言。我正在尝试模拟一种没有发送 cookie 的情况,以便我可以忽略这种影响。

【问题讨论】:

  • 标题的顺序不重要。
  • 谢谢。那么还有什么可以搞砸呢? TCP?

标签: java http post httpurlconnection


【解决方案1】:

首先,标题的顺序无关紧要。

其次,为了手动覆盖host 标头,您需要在代码中设置sun.net.http.allowRestrictedHeaders=true

System.setProperty("sun.net.http.allowRestrictedHeaders", "true")

或在 JVM 启动时

-Dsun.net.http.allowRestrictedHeaders=true

这是 Oracle 前段时间引入的安全预防措施。那是因为根据RFC

Host 请求头字段指定 Internet 主机和端口 被请求的资源的数量,从原始资源中获得 由用户或引用资源提供的 URI(通常是 HTTP URL)。

【讨论】:

  • 感谢大家对此发表评论。如果标头字段的顺序无关紧要,那么在这种情况下,解决方案就不是 HTTP 级别的。我试试 Apache 的 Http Components,否则我真的需要搞乱底层协议层。
  • FWIW,有一个警告“标题的顺序无关紧要” - per RFC 7230,“接收标题字段的顺序具有不同的字段名称不重要”。
【解决方案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());

Marcel Stör 在第一个答案中回答了第二个问题。 一个

【讨论】:

    【解决方案3】:

    我对 Apache Http 组件很幸运,我猜是“主机”标头缺少“www”。有所作为,可以使用 Apache 的 HttpPost 完全按照预期进行设置:

    httpPost.setHeader("Host", "www.thewebsite.com");
    

    Wireshark 的输出证实了我的怀疑。这一次,我的 HTTP 帖子之前的 TCP 通信看起来不同 (client ---> server, server ---> client, client ---> server) 而不是 (client ---> server, server --->客户端,客户端--->服务器,客户端--->服务器)。

    现在我得到了所需的 Location 标头值,并且服务器也在设置 cookie。 :)

    这个问题大部分都解决了。

    实际上,我想使用 lightweihgt HttpUrlConnection,因为这就是 Android Developers 博客的建议。 System.setProperty("sun.net.http.allowRestrictedHeaders", "true") 也可以工作,如果它允许“www”。在Host 值中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多