gpt4 book ai didi

java - 在 https 连接 header 中设置用户代理属性

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:55:00 24 4
gpt4 key购买 nike

我无法为 https 连接正确设置 user-agent 属性。根据我收集到的信息,可以通过 -Dhttp.agent VM 选项或通过 URLConnection.setRequestProperty() 设置 http-header 属性。 .但是,通过 VM 选项设置用户代理会导致“Java/[version]”附加到 http.agent 的任何值。同时 setRequestProperty() 只适用于 http 连接,不适用于 https(至少我试过的时候是这样)。

java.net.URL url = new java.net.URL( "https://www.google.com" );
java.net.URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
conn.connect();
java.io.BufferedReader serverResponse = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));
System.out.println(serverResponse.readLine());
serverResponse.close();

我通过使用 WireShark 检查 http 通信发现/验证了问题。有什么办法解决这个问题吗?

更新:附加信息

看来我对通信的了解还不够深入。代码从代理后面运行,因此观察到的通信是针对代理的,通过 -Dhttps.proxyHost 设置,而不是目标网站 (google.com)。总之,在 https 连接期间,方法是 CONNECT,而不是 GET。这是 https 通信尝试的 wireshark 捕获。就像我上面提到的,用户代理是通过 -Dhttp.agent 设置的,因为 URLConnection.setRequestProperty() 没有效果(user-agent = Java/1.7.0) .在这种情况下,请注意附加的 Java/1.7.0。问题仍然存在,为什么会发生这种情况,我该如何解决?

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0 Java/1.7.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Proxy-Connection: keep-alive

HTTP/1.1 403 Forbidden
X-Bst-Request-Id: MWPwwh:m7d:39175
X-Bst-Info: ch=req,t=1366218861,h=14g,p=4037_7213:1_156,f=PEFilter,r=PEBlockCatchAllRule,c=1905,v=7.8.14771.200 1363881886
Content-Type: text/html; charset=utf-8
Pragma: No-cache
Content-Language: en
Cache-Control: No-cache
Content-Length: 2491

顺便说一句,请求被禁止,因为代理过滤用户代理,Java/1.7.0 导致拒绝。我已将 Java/1.7.0 附加到 http 连接的用户代理,但代理也拒绝连接。我希望我不会发疯 :)。

最佳答案

I've found/verified the problem by inspecting http communictions using WireShark. Is there any way around this

这是不可能的。通过 SSL 套接字进行的通信完全被加密协议(protocol)所掩盖,无法随意观察。使用数据包捕获软件,您将能够查看 SSL 连接的启动和加密数据包的交换,但这些数据包的内容只能在连接的另一端(服务器)提取。如果不是这种情况,那么整个 HTTPS 协议(protocol)将损坏,因为它的全部目的是保护 HTTP 通信免受中间人类型的攻击(在这种情况下MITM 是数据包嗅探器)。

HTTPS 请求捕获示例(部分):

.n....E... .........../..5..3..9..2..8.. ..............@........................Ql.{...b....OsR..!.4.$.T...-.-.T....Q...M..Ql.{...LM..L...um.M...........s. ...n...p^0}..I..G4.HK.n......8Y...............E...A..>...0...0......... ).s.......0 ..*.H.. .....0F1.0...U....US1.0...U. . Google Inc1"0 ..U....Google Internet Authority0.. 130327132822Z. 131231155850Z0h1.0...U....US1.0...U... California1.0...U... Mountain View1.0...U. . Google Inc1.0...U....www.google.com0..0

理论上,了解您的 User-Agent header 是否实际被排除的唯一方法是您是否可以访问 Google 服务器,但实际上 HTTPS 规范或 Java 中没有任何内容它的实现排除了通常通过 HTTP 发送的 header 。

HTTP 请求捕获示例:

GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Connection: keep-alive

两个示例捕获都是使用完全相同的代码生成的:

URL url = new URL(target);
URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
conn.connect();
BufferedReader serverResponse = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
System.out.println(serverResponse.readLine());
serverResponse.close();

除了 HTTPS 的目标是“https://www.google.com”,而 HTTP 的目标是“http://www.google.com”。


编辑 1:

根据您更新的问题,使用 -Dhttp.agent 属性确实将“Java/version”附加到用户代理 header ,如 following documentation 所述:

http.agent (default: “Java/<version>”)
Defines the string sent in the User-Agent request header in http requests. Note that the string “Java/<version>” will be appended to the one provided in the property (e.g. if -Dhttp.agent=”foobar” is used, the User-Agent header will contain “foobar Java/1.5.0” if the version of the VM is 1.5.0). This property is checked only once at startup.

“违规”代码位于 sun.net.www.protocol.http.HttpURLConnection 的静态 block 初始值设定项中:

static {
// ...
String agent = java.security.AccessController
.doPrivileged(new sun.security.action.GetPropertyAction(
"http.agent"));
if (agent == null) {
agent = "Java/" + version;
} else {
agent = agent + " Java/" + version;
}
userAgent = agent;

// ...
}

解决此“问题”的一种下流方法是这段代码,我 1000% 建议您不要使用:

protected void forceAgentHeader(final String header) throws Exception {
final Class<?> clazz = Class
.forName("sun.net.www.protocol.http.HttpURLConnection");

final Field field = clazz.getField("userAgent");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, header);
}

将此覆盖与 https.proxyHosthttps.proxyPorthttp.agent 设置一起使用可获得所需的结果:

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Proxy-Connection: keep-alive

但是,是的,不要那样做。使用 Apache HttpComponents 更安全:

final DefaultHttpClient client = new DefaultHttpClient();
HttpHost proxy = new HttpHost("127.0.0.1", 8888, "http");
HttpHost target = new HttpHost("www.google.com", 443, "https");
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpProtocolParams
.setUserAgent(client.getParams(),
"Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
final HttpGet get = new HttpGet("/");

HttpResponse response = client.execute(target, get);

关于java - 在 https 连接 header 中设置用户代理属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15845075/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com