当前位置: 首页 > 面试题库 >

在https连接头中设置用户代理属性

巫马山
2023-03-14
问题内容

我无法正确设置user-agenthttps连接的属性。根据我的收集,可以通过-Dhttp.agentVM选项或通过设置http-
header属性URLConnection.setRequestProperty()。但是,通过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()它无效(用户代理=
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连接的用户代理中,并且代理也拒绝连接。我希望我不会发疯:)。


问题答案:

我已经通过使用WireShark检查http通讯来发现/验证了问题。有没有办法解决

这是不可能的。通过SSL套接字进行的通信完全被加密协议的偶然观察所遮盖。使用数据包捕获软件,您将能够查看SSL连接的启动和加密数据包的交换,但是这些数据包的内容只能在连接的另一端(服务器)中提取。如果不是这种情况,那么整个HTTPS协议都会被
破坏 ,因为它的重点是保护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确实排除了标头的唯一方法是您是否有权访问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();

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

编辑1:

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

http.agent (默认值:“ Java / <版本>”)
定义在HTTP请求中的User-Agent请求标头中发送的字符串。请注意,字符串“ Java /
”将附加到属性中提供的字符串(例如,如果使用-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;

    // ...
}

围绕此“问题”的一种淫秽方式是以下代码片段,我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.agentset 一起使用此覆盖可提供所需的结果:

CONNECT www.google.com:443 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,图片/ 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);


 类似资料:
  • 我试图从react(带有redux)前端outlook add-id发出请求,它使用Axios在HTTPS上运行。我想在package.json中使用代理设置,因此我只需要在请求中使用/path/to/endpoint。然而,后端是在http上运行的,当两者都在本地主机上时,axios似乎不使用代理设置,也不会重新定向到非httpsendpoint。我尝试过在https上运行后端,将请求发送到安全

  • 问题内容: 要指定SQLite连接属性,请使用org.sqlite.SQLiteConfig,它的内容如下: 使用c3p0创建连接池的过程如下: 问题:如何创建结合了两者的数据源,让我设置诸如连接池的最大池大小和sqlite的同步模式之类的东西? 问题答案: 尝试 现在,数据源将是c3p0 PooledDataSource,它包装了已根据需要配置的SQLite未池化数据源。 请参阅C3P0的文档,

  • 我有一个奇怪的小问题:如何设置截击中的用户代理? 我需要一些网站的完整版本(桌面版),而不是手机版。 我试图将变量userAgent从“volley/0”改为“Mozilla/5.0(X11;Linux i686)AppleWebKit/537.36(KHTML,比如Gecko)Chrome/27.0.1453.93 Safari/537.36”(我的Chrome)。没什么区别。 有什么建议吗?

  • 我一直在工作的Apache骆驼连接https URLS'通过提供TLS证书通过代理,但得到错误org.apache.http.conn.不支持的模式异常:超文本传输协议不支持 下面是驼峰路由和带有代理的ssl上下文 公共类HttpProxyRouter扩展了RouteBuilder{ } 遇到错误 org.apache.catalina.core.Application Context logIN

  • 先决条件 Apache Tomcat 7 Spring3.2.11。释放 Apache Camel 2.14.1 Camel HTTP4endpoint(Camel-HTTP4) 问题 我尝试通过http4组件调用https加密站点。位于我的服务器和Internet(目标服务器)之间的代理检查标头“User-Agent”并在请求为空时拒绝请求。 连接请求不包含http标头“User Agent”。

  • 我试图连接到java远程mysql服务器,从ip111.111.111.111到ip111.111.111.222JDBC连接器: user@111.111.111.111在数据库中创建,GRANTS工作正常。 数据库中不存在user@localhost,因为我认为没有必要。 防火墙允许连接。 由于某种原因,当我尝试启动连接时,会生成一个异常: 但我请求IP111.111.111.111连接 注意