Ответ 1
Я нашел/подтвердил эту проблему, проверив http-протоколы с помощью WireShark. Есть ли какой-либо путь вокруг этого
Это невозможно. Связь через сокет SSL полностью скрывается от случайного наблюдения по протоколу шифрования. Используя программное обеспечение для захвата пакетов, вы сможете просмотреть инициирование SSL-соединения и обмен зашифрованными пакетами, но содержимое этих пакетов можно извлечь только на другом конце соединения (сервер). Если бы это было не так, то протокол HTTPS в целом был бы сломан, так как в целом он должен защищать HTTP-связь от атак типа "человек в середине" (где в этом случае MITM является сниффером пакетов).
Пример. Захват запроса HTTPS (частичный):
.n.... E............../.. 5..3..9..2..8................ @........................ Ql. {... б.... OSR..!. 4. $. Т...,.. T.... Q... M..Ql. {... LM..L... um.M........... s.... п... р ^ 0}.. I..G4.HK.n...... 8Y............... E... A.. > ... 0... 0.........).s....... 0..*.ЧАС....... 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
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv: 19.0) Gecko/20100101 Firefox/19.0
Хост: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q =.2,/; д = 0,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.agent(по умолчанию: "Java/<version> " )
Определяет строку, отправленную в заголовке запроса User-Agent в http-запросах. Обратите внимание, что строка "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;
// ...
}
Нецензурным способом этой "проблемы" является этот фрагмент кода, который я рекомендую вам на 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
, вы получите желаемый результат:
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
Accept: text/html, image/gif, image/jpeg, *; q =.2,/; д = 0,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);