在https连接头中设置user-agent属性

use*_*279 10 java https http-headers

我无法正确设置user-agenthttps连接的属性.根据我收集的内容,可以通过-Dhttp.agentVM选项或通过设置http-header属性URLConnection.setRequestProperty().但是,通过VM选项设置user-agent会导致"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();
Run Code Online (Sandbox Code Playgroud)

我通过使用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
Run Code Online (Sandbox Code Playgroud)

顺便说一下,由于代理过滤用户代理,因此禁止请求,Java/1.7.0导致拒绝.我已将Java/1.7.0附加到http连接的用户代理,代理也拒绝连接.我希望我不会疯狂:).

Per*_*ion 12

我通过使用WireShark检查http通信找到/验证了问题.有没有办法解决

这是不可能的.通过加密协议的偶然观察,SSL套接字上的通信完全变得模糊.使用数据包捕获软件,您将能够查看SSL连接的启动和加密数据包的交换,但这些数据包的内容只能在连接的另一端(服务器)中提取.如果情况并非如此,则整个HTTPS协议将被破坏,因为它的全部意义是保护来自中间人类型攻击的HTTP通信(在这种情况下,MITM是数据包嗅探器) .

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

.n .... E ... .........../.. 5..3..9..2..8 .. ........... ... @ ........................ QL.{... b ....没有OSR ..!4.$:T. .. - ..牛逼.... Q ... M..Ql.{... ... LM..L ........... um.M秒.... N ... P 1 0} .. I..G4.HK.n ...... 8Y ...............è...一个... > ... 0 ... 0 .........).s ....... 0 ..*.H .. ..... 0F1.0 ...... U .. ..US1.0 ...ü..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标头是否实际被排除的唯一方法是,您是否可以访问Google服务器,但实际上,HTTPS规范或Java的实现中没有任何内容排除通常已发送的标头HTTP.

示例捕获HTTP请求:

GET/HTTP/1.1
用户代理:Mozilla/5.0(Windows NT 5.1; rv:19.0)Gecko/20100101 Firefox/19.0
主机:www.google.com
接受:text/html,image/gif,image/jpeg,*; q = .2,/ ; q = .2
连接:保持活着

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

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();
Run Code Online (Sandbox Code Playgroud)

除了HTTPS,目标是" https://www.google.com ",对于HTTP,它是" http://www.google.com ".


编辑1:

根据您更新的问题,使用该-Dhttp.agent属性确实会将"Java/version"附加到用户代理标头,如以下文档所述:

http.agent(默认值:"Java/<version>")
定义http请求中User-Agent请求标头中发送的字符串.请注意,字符串"Java/<version>"将附加到属性中提供的字符串(例如,如果使用-Dhttp.agent ="foobar",则User-Agent标头将包含"foobar Java/1.5.0"如果VM的版本是1.5.0).此属性仅在启动时检查一次.

'违规'代码在静态块初始化器中sun.net.www.protocol.http.HttpURLConnection:

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;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

围绕这个"问题"的一种淫秽方式是这段代码,我强烈建议你不要使用:

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);
}
Run Code Online (Sandbox Code Playgroud)

使用此覆盖有https.proxyHost,https.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
主机:www.google.com
接受:text/html,image/gif, image/jpeg,*; q = .2,/ ; q = .2
代理连接:保持活动状态

但是,不要这样做.使用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);
Run Code Online (Sandbox Code Playgroud)