Задать свойство user-agent в заголовке соединения https
Я не могу правильно установить user-agent
свойство для соединения https. Из того, что я собрал, свойства http-заголовка могут быть установлены через -Dhttp.agent
опция VM или через URLConnection.setRequestProperty()
. Однако установка user-agent через параметр VM приводит к добавлению" Java/[version] " к любому значению http.агент. В то же время 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();
Я нашел / проверил проблему, проверив http-связи с помощью WireShark. Есть ли способ обойти это?
Обновление: Дополнительная Информация
кажется, я недостаточно глубоко заглянул в сообщение. Код выполняется из-за прокси-сервера, поэтому наблюдаемая связь против прокси-сервера, установленного через -Dhttps.proxyHost
, а не целевой веб-сайт (google.com). Во всяком случае, во время https-соединения метод CONNECT
, а не GET
. Вот как Wireshark захват попытки связи https. Как я уже упоминал выше, user-agent устанавливается через -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
кстати, запрос запрещен, потому что прокси фильтрует user-agent,Java / 1.7.0 вызывает отторжение. Я добавил Java / 1.7.0 пользователю-агенту http-соединения и прокси тоже отказывается от соединения. Надеюсь, я не схожу с ума :).
2 ответов
Я нашел / проверил проблему, проверив http-коммуникации с помощью WireShark. Есть ли способ обойти это
это невозможно. Связь через SSL-сокет полностью скрыта от случайного наблюдения протоколом шифрования. Используя программное обеспечение для захвата пакетов, вы сможете просмотреть инициализацию SSL-соединения и обмен зашифрованными пакетами, но содержимое этих пакетов может быть извлечено только на другом конце соединение (сервер). Если бы это было не так, то протокол HTTPS в целом был бы сломанные, поскольку весь смысл в том, чтобы защитить HTTP-связь от атак типа "человек в середине" (где в этом случае MITM является сниффером пакетов).
пример захвата запроса HTTPS (частичный):
.северный....Е... .........../..5..3..9..2..8.. ..............@........................КЖ.{...си....ЛРН..!.4.$.Т...-.-.Т....Вопрос:..М..КЖ.{...ЛЮМЕН..Л...ГМ.М...........s. ...n ... p^0}..I..G4.HK.n......8Y...............E ... A..> ... 0 ... 0......... ).с.......Ноль ..*.Х.. .....0F1.0...у....США1.0...США . Google В Ходе МКП-1"0 ..У....Google Internet Authority0.. 130327132822Z. 131231155850Z0h1.0 ... U....US1.0 ... U... California1.0...У... Горы Представление1.0...У. . Google Inc1.0 ... U....www.Гугл.com0..0
теоретически единственный способ узнать, если ваш User-Agent
заголовок фактически исключается, если у вас есть доступ к серверам Google, но на самом деле нет ничего в спецификации HTTPS или реализации Java, которая исключает заголовки, которые обычно были бы отправлены по HTTP.
пример захвата HTTP-запроса:
GET/HTTP / 1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox / 19.0
Хозяин: www.google.com
Примите: текст / html, изображение / gif, изображение / jpeg,*; q=.2, /; q=.2
Соединение: 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" в заголовок агента пользователя, как описано в следующая документация:
протоколу HTTP.агент!--16--> (по умолчанию: "Java/
")
Определяет строку, отправленную в заголовке запроса User-Agent в http-запросах. Обратите внимание, что строка "Java/" будет добавлена к строке, указанной в собственность (например, если -Dhttp.agent=используется" foobar", заголовок User-Agent будет содержать" Foobar Java/1.5.0", если версия виртуальной машины 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.proxyHost
, https.proxyPort
и http.agent
set дает желаемый результат:
подключение 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
Примите: текст / html, изображение / gif, изображение / jpeg,*; q=.2, /; q=.2
Прокси-соединение: 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);
Я нашел / проверил проблему, проверив http-коммуникации с помощью WireShark. Есть ли способ обойти это?
здесь нет никаких проблем. Заголовок User-Agent задает, будет ли запрос транспортироваться через HTTP / HTTPS. Даже установить его на что-то неразумное, как blah blah
работает по HTTPS. Заголовки, показанные ниже, были захвачены, когда используемый базовый протокол был HTTPS.
заголовки запросов, отправленные через Протоколу HTTPS
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
User-Agent: blah blah
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
вот код, который запускает запрос.
// localhost:52999 is a reverse proxy to xxx:443
java.net.URL url = new java.net.URL( "https://localhost:52999/" );
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();
обычно HTTPS-запросы не могут быть обнюханы (например, @Perception). Передача запроса через прокси-сервер, который заменяет корневой ЦС собственным поддельным ЦС, позволит вам видеть трафик. Более простой способ-просто посмотреть журнал доступа целевого сервера. Но, как вы можете видеть из фрагмента запроса HTTPS выше,User-Agent
заголовок, который направляется правильный.