Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347

Достучаться через прокси с помощью сертификата (и прочего)

09.10.2019, 20:23. Показов 3516. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброе время суток.

Работаю в фирме, накрытой Великой Проксей: любой доступ во внешние адреса - только через прокси. Иначе никак.

Дали задание сделать на Яве скачиватель данных с Я.Метрики. Ява - не мой профильный инструмент (да, даже если бы и был профильным) - вот всего этого д***ма я не понимаю. То есть не понимаю всей концепции сертификатов (да и как это понять без употребления?).
________________________________________ ________________________________________ _________________________

Попробовал постучаться напрямую - access denied. Что логично - мы накрыты проксей.
Добавил нужные строки:
Java
1
2
3
4
5
6
7
8
9
10
11
12
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port));
 
URL url = new URL(urlString);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(proxy);
 
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
try (in) {
    return in.lines().reduce(new StringBuffer(), StringBuffer::append, null).toString().trim();
} catch (RuntimeException e) {
    e.printStackTrace();
    //throw e;
}
Получилось пройти через проксю, но выпала ошибка сертификата:
"javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPa thBuilderException: unable to find valid certification path to requested target"

Тогда начал искать, как решить эту ошибку и нашел... *Пропускаю несколько шагов, к которым я вернусь позже*

Скачиваем для начала сертификат вот этим:
Bash
1
openssl s_client -connect api-metrika.yandex.ru:443 | sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p'
И запихиваем сертификат внутрь Коннекшена.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port));
 
String certt = ReadFlNew("C:\\Users\\qqluser\\Downloads\\cert.txt");
ByteArrayInputStream derInputStream = new ByteArrayInputStream(certt.getBytes());
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
String alias = "alias";//cert.getSubjectX500Principal().getName();
 
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(trustStore, null);
KeyManager[] keyManagers = kmf.getKeyManagers();
 
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
 
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
 
URL url = new URL(urlString);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(proxy);
//conn.setSSLSocketFactory(sslContext.getSocketFactory());
 
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
try (in) {
    return in.lines().reduce(new StringBuffer(), StringBuffer::append, null).toString().trim();
} catch (RuntimeException e) {
    e.printStackTrace();
    //throw e;
}
Ошибка не исчезла. И даже не изменилась. Мне кажется, что этот код был проскипан.


*Теперь возвращаемся к шагам, которые я пропустил*
Они мне изначально не понравились. Так как предлагают импортировать сертификат в общее хранилище. Это где такое видано, чтобы алгоритм лез в данные?!
Но это советуют все: например тут или тут.

Ладно, попробовал. Естественно, оно мне не дало импортировать в хороший файл всякий мусор, отказав в доступе.

________________________________________ ________________________________________ _________________________

Но как быть теперь?

Я не понимаю двух вещей:
1. Что такое сертификат, и нафига он нужен.
Если предположить, что серт - это некое удостоверение (типа пароля), что "я это я", то я в принципе не понимаю, как можно запрашивать сертификат по тому же каналу, что и буду общаться. Это все равно, что на весь офис кричать: " -Вася, давай мы придумаем тебе секретное слово, чтобы сразу понимать, что это ты! - Давай, это слово: "пароль-полироль"!.." И вот уже все в офисе могут представляться Васей по этому "сертификату"...

2. (более насущное)
И как мне быть? Как подключиться и скачать данные с яндекс.метрики? Какие-таки действия мне нужно провернуть?
2.1. Желательно, чтобы ничего никуда не импортировать - это же бред. Если нужно дополнительное хранилище ключей - это должно быть отдельное, а одно смержденное.


Помогите, пожалуйста.


PS: вы так боитесь слово "помощь", что нельзя нормально написать заголовок.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.10.2019, 20:23
Ответы с готовыми решениями:

Как сделать с помощью фильтров в "Политиках безопасности IP чтобы http трафик открывался через прокси сервер?
Здравствуйте. Как сделать так, чтобы http трафик открывался через прокси сервер? Это нужно сделать с помощью фильтров в "Политиках...

Как быстро скачивать через прокси с файлообменников или без использования прокси
Доброго времени суток, как вы возможно знаете, для загрузки с облака маил ру или ядаа пользователи из хохляндии вынуждены использовать...

При передаче post запроса через прокси сервер в ответ приходят ошибки с прокси сервера
При передаче post запроса через прокси сервер в ответ прилетают ошибки с прокси сервера: <p><b>Invalid Request</b>...

15
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
09.10.2019, 21:49
Цитата с сайта апи яндекс метрики
Для использования API Яндекс.Метрики необходимо получить авторизационный токен через OAuth-сервер Яндекса. Токен необходимо передавать для каждого метода в HTTP-заголовке Authorization.
Code
1
2
3
4
5
GET /management/v1/counters HTTP/1.1
Host: api-metrika.yandex.net
Authorization: OAuth 05dd3dd84ff948fdae2bc4fb91f13e22bb1f289ceef0037
Content-Type: application/x-yametrika+json
Content-Length: 123
Если метод API вызван без токена или в запросе передан недействительный токен, сервер возвращает HTTP-статус 401 Unauthorized
Там ни слова про сертификаты
Добавить заголовок к запросу это метод setRequestProperty
conn.setRequestProperty("key", "value");
где key - название заголовка с заглавной буквы без двоеточия и проверяйте метод getResponseCode()
0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
09.10.2019, 23:17  [ТС]
Цитата Сообщение от alecss131 Посмотреть сообщение
Там ни слова про сертификаты
А причем тут АПИ яндекса, если вот ошибка: "javax.net.ssl.SSLHandshakeException : PKIX path building failed: sun.security.provider.certpath.SunCertPa thBuilderException: unable to find valid certification path to requested target"

Я же изначально делал просто HTTP-запрос, без всего. И, если бы не было проблем с сертом, то и разбирался бы я сейчас с АПИ Яндекса, но я даже добраться-то до апи не могу.


PS: АПИшка должна была вернуть джейсон вида: "вы не авторизованы".
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
09.10.2019, 23:53
Если по ошибке сертификата то тут гугл выдал что ява не принимает сертификат сервера (предположу яндекса), и нашел решение не передавать сертификат яндексу а установить сертификат в хранилище
Windows Batch file
1
keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt
Либо вообще отключите проверку сертификатов в запросе следующим кодом
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
           return null;
          }
          @Override
          public void checkClientTrusted(X509Certificate[] arg0, String arg1)
           throws CertificateException {}
 
          @Override
          public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {}
          }
     };
 
  SSLContext sc=null;
  try {
   sc = SSLContext.getInstance("SSL");
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  }
  try {
   sc.init(null, trustAllCerts, new java.security.SecureRandom());
  } catch (KeyManagementException e) {
   e.printStackTrace();
  }
  HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  // Create all-trusting host name verifier
  HostnameVerifier validHosts = new HostnameVerifier() {
  @Override
  public boolean verify(String arg0, SSLSession arg1) {
   return true;
  }
  };
  // All hosts will be valid
  HttpsURLConnection.setDefaultHostnameVerifier(validHosts);
Либо
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
SSLContext context = SSLContext.getInstance("TLSv1.2");
TrustManager[] trustManager = new TrustManager[] {
    new X509TrustManager() {
       public X509Certificate[] getAcceptedIssuers() {
           return new X509Certificate[0];
       }
       public void checkClientTrusted(X509Certificate[] certificate, String str) {}
       public void checkServerTrusted(X509Certificate[] certificate, String str) {}
    }
};
context.init(null, trustManager, new SecureRandom());
 
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
Добавлено через 22 минуты
На сколько я все это понимаю. В яве есть хранилище доверенных сертификатов, если там нету сертификата то ява плюется ошибками. У меня было нечто похожее когда я игрался со своим https сервером с самоподписанным сертификатом. И в решениях предлагается не в файл сертификата чтото добавлять а сам сертификат добавить в хранилище явы.
То есть сам сертификат это ничего по сути, так как вместе с сертификатом должна идти информация о доверии ему. А это как раз наличие сертификата в общем хранилище.
Да и в вашем коде использование кода который использует сертификат закомментировано
Java
1
//conn.setSSLSocketFactory(sslContext.getSocketFactory());

Не по теме:

keystore — это специализированное хранилище секретных данных, которое используется Java-приложениями для шифрования, аутентификации и установки HTTPS соединений. Так, для аутентификации клиента и сервера, устанавливающих SSL (Secure Sockets Layer — уровень защищённых cокетов) соединение, требуются приватные ключи и сертификаты. Если используется односторонняя аутентификация, то keystore используется только на серверной стороне. При двусторонней аутентификации клиент и сервер обмениваются сертификатами; соответственно и у сервера, и у клиента должны быть keystore с парой ключей private/public + сертификат. Иными словами keystore используется для хранения ключей и сертификатов, применяемых для идентификации владельца ключа (клиента или сервера).

0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
10.10.2019, 10:58  [ТС]
Цитата Сообщение от alecss131 Посмотреть сообщение
Если по ошибке сертификата то тут гугл выдал что ява не принимает сертификат сервера (предположу яндекса), и нашел решение не передавать сертификат яндексу а установить сертификат в хранилище
Bash
1
keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt
Я это тоже нашел. Вот только не понял, что такое "keystore" - это только стандартный C:\Program Files\Java\jdk-13\lib\security\cacerts, или любой файл? А как его тогда прокинуть новое хранилище, чтобы ява узнала о его существовании?..

________________________________________ _____________________

Цитата Сообщение от alecss131 Посмотреть сообщение
Либо вообще отключите проверку сертификатов в запросе следующим кодом
А вот это уже интересно. Сегодня попробую.

Спасибо.

Добавлено через 1 час 35 минут
Цитата Сообщение от alecss131 Посмотреть сообщение
Да и в вашем коде использование кода который использует сертификат закомментировано
PS: не заметил. Просто я написал код, который как бы юзал сертификат - ошибка есть. Тогда я закоментил строку, убрав взаимодействие с сертом - хотел посмотреть, как это повлияет на конечную ошибку. Никак не повлияло.
А при копировании кода сюда - забыл убрать.
0
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
10.10.2019, 11:01
Vhodnoylogin, если есть возможность отключить проверку, лучше так и сделать. Корпаративные SSL прокси это довольно сложная штука. Обычно они подменяют корневой сертификат чтобы работать, но если не знать принцип работы сертификатов, объяснить это будет невозможно

Цитата Сообщение от Vhodnoylogin Посмотреть сообщение
Если предположить, что серт - это некое удостоверение (типа пароля), что "я это я", то я в принципе не понимаю, как можно запрашивать сертификат по тому же каналу, что и буду общаться. Это все равно, что на весь офис кричать: " -Вася, давай мы придумаем тебе секретное слово, чтобы сразу понимать, что это ты! - Давай, это слово: "пароль-полироль"!.." И вот уже все в офисе могут представляться Васей по этому "сертификату"...
Для этого придумали ассиметричное шифрование.
То есть если Вася хочет говорить с Петей, петя генерирует пару ключей приватный\публичный

* Приватный ключ Петя не говорит никому
* Публичный ключ Петя кричит на весь оффис
* Петя шифрует сообщение приватным ключом и отправляет Васе
* Любой (в том числе Вася) может расшифровать это сообщение используя публичный ключ, который Петя крикнул на весь оффис
* Вася получает сообщение и применяет публичный ключ Пети чтобы его расшифровать. Если у него это получилось, значит сообщение точно от Пети т.к больше никто не может зашифровать сообщение таким образом чтобы его можно было расшифровать с Петиным публичным ключом.

Вот так работает ассиметричное шифрование и именно за этим нужны сертификаты.
В данном случае это тебе не сильно поможет в решении проблемы, но ты хотя бы будешь чуть больше понимать что происходит)

Чтобы решить проблему тебе нужно следующее
Запусти запрос не через джаву, а через любой рест клиент (можно даже чере браузер)
Посмотри нет ли ошибки сертификата.
Если есть, смело иди в IT отдел и говори чтобы пофиксили
Если ошибки нет, ищи проблему в своем коде
1
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
10.10.2019, 12:04
Лучший ответ Сообщение было отмечено Vhodnoylogin как решение

Решение

Долго я возился с отключением проверки, в сети все способы не помогали (по крайней мере на моем самоподписанном сервере) и ява плевалась ошибками, помог только такой код
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            } };
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
            SSLContext sc = SSLContext.getInstance("SSL"); 
            sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
Вот этот код до строчки
Цитата Сообщение от Vhodnoylogin Посмотреть сообщение
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(proxy);
Запросы перестали плеваться ошибками, причем без setDefaultHostnameVerifier и сервер тоже сыпал ошибки
1
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
10.10.2019, 12:44  [ТС]
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
* Приватный ключ Петя не говорит никому
* Публичный ключ Петя кричит на весь оффис
* Петя шифрует сообщение приватным ключом и отправляет Васе
* Любой (в том числе Вася) может расшифровать это сообщение используя публичный ключ, который Петя крикнул на весь оффис
* Вася получает сообщение и применяет публичный ключ Пети чтобы его расшифровать. Если у него это получилось, значит сообщение точно от Пети т.к больше никто не может зашифровать сообщение таким образом чтобы его можно было расшифровать с Петиным публичным ключом.
В этой схеме есть слабое место - когда Петя говорит на весь офис публичный ключ, то мы не знаем, что это говорит именно Петя, а не Сережа.
В итоге Сергей может вначале представившись Петей разослать всем ключи, а потом общаться со всеми от его имени - и слать всякую похабщину (вроде вирусни) без вреда для своей репутации и во вред Пети в конечным пользователям.

То есть я не доверяю сообщению, но доверяю ключу, которое тоже является сообщением?..

________________________________________ ________________________________________ ___________

Цитата Сообщение от KEKCoGEN Посмотреть сообщение
Запусти запрос не через джаву, а через любой рест клиент (можно даже чере браузер)
Посмотри нет ли ошибки сертификата.
Если есть, смело иди в IT отдел и говори чтобы пофиксили
Если ошибки нет, ищи проблему в своем коде
Я открываю в браузере нормально, только через яву проблемы.

Но я еще не пытался доверится всем сертификатам (из других ответов в этой теме).
0
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
10.10.2019, 12:53
Цитата Сообщение от Vhodnoylogin Посмотреть сообщение
В этой схеме есть слабое место
Слабое место есть в недостаточно подробном объяснении (подробное тут приводить смысла не вижу), а не в самой схеме. Сама схема не имеет известных слабых мест и используется уже много лет. Если есть желание изучить методы передачи более подробно, можно воспользоваться гуглом. Подробных статей на эту тему миллион.
0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
10.10.2019, 12:54  [ТС]
Цитата Сообщение от alecss131 Посмотреть сообщение
Долго я возился с отключением проверки, в сети все способы не помогали (по крайней мере на моем самоподписанном сервере) и ява плевалась ошибками, помог только такой код
Спасибо.
Результат: "java.io.IOException: Server returned HTTP response code: 401 for URL:"
То есть теперь я нормально подключаюсь к серверу и получаю человеческие ошибки. Которые можно по-человечески править.
________________________________________ ______________

KEKCoGEN, но и за описание, как работает сертификат, спасибо - стало понятнее. И стало понятнее, что значит "довериться всем сертификатам".
________________________________________ ______________

Осталось только разобраться, как минимальным количеством кода, довериться всем сертификатам.
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
10.10.2019, 13:05
Цитата Сообщение от Vhodnoylogin Посмотреть сообщение
Осталось только разобраться, как минимальным количеством кода, довериться всем сертификатам.
Имхо меньше 16 строчек из последнего кода это вряд ли сделать. Да и то в нем есть строчки состоящие из одних скобок. Да и к чему минимальное количество кода? Куда еще меньше?
0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
10.10.2019, 14:10  [ТС]
Цитата Сообщение от alecss131 Посмотреть сообщение
Да и к чему минимальное количество кода? Куда еще меньше?
Хатю в функциональном стиле... Вот только не получится, видимо. Придется свою обертку писать для функциональщины.
0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
11.10.2019, 17:34  [ТС]
Понять бы теперь, как с этим яндексом работать...

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
public class DownloadWebService {
    public String createArgumentedUrl(String url, List<Pair<String, String>> args) throws RuntimeException {
        final String PH_QSTN = "?";
        final String PH_EQUAL = "=";
        final String PH_AMPR = "&";
 
        if (args != null) {
            StringBuffer sbf = args.stream().reduce(
                    new StringBuffer().append(url).append(PH_QSTN)
                    , (res, x) -> res.append(x.getLeft()).append(PH_EQUAL).append(x.getRight()).append(PH_AMPR)
                    , StringBuffer::append
            );
            sbf.deleteCharAt(sbf.length() - 1);
            return sbf.toString();
        }
        return url;
    }
 
    protected String send(String url, List<Pair<String, String>> header, HTTPRequestType reqType) {
        try {
            final String hostname = "bcpsg-moscow.headoffice.psbank.local";
            final int port = 8080;
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port));
 
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null
                    , new TrustManager[]{
                            new X509TrustManager() {
                                @Override
                                public X509Certificate[] getAcceptedIssuers() {
                                    return null;
                                }
 
                                @Override
                                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                                }
 
                                @Override
                                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                                }
                            }
                    }, new java.security.SecureRandom()
            );
 
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier((hostname1, session) -> true);
            HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection(proxy);
            if (header != null) {
                header.forEach(x -> conn.setRequestProperty(x.getLeft(), x.getRight()));
            }
            conn.setRequestMethod(reqType.toString());
 
//            conn.getRequestProperties().forEach((x, l) -> {
//                String res = x + ' ' + l.stream().reduce("", (z, y) -> z + " " + y);
//                System.out.println(res);
//            });
 
            if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                try (in) {
                    return in.lines().reduce(new StringBuffer(), StringBuffer::append, StringBuffer::append).toString().trim();
                }
            }
            conn.getHeaderFields().entrySet().stream().forEach((x) -> {
                //String res = x + ' ' + l.getValue().stream().reduce("", (z, y) -> z + " " + y);
                System.out.println(x);
            });
            //finally { in.close(); }
        } catch (NoSuchAlgorithmException | KeyManagementException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public String sendGet(String url, List<Pair<String, String>> header) {
        return send(url, header, HTTPRequestType.GET);
    }
 
    public String sendPost(String url, List<Pair<String, String>> header) {
        return send(url, header, HTTPRequestType.POST);
    }
 
    public <T> T parseJSON(String json, Class<T> classOfT) {
        try {
            return (
                    new GsonBuilder().registerTypeAdapter(
                            LocalDateTime.class
                            , (JsonDeserializer<LocalDateTime>) (json1, type, jsonDeserializationContext) ->
                                    LocalDateTime.parse(json1.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME))
            )
                    .create()
                    .fromJson(json, classOfT);
        }
        catch (RuntimeException e){
            e.printStackTrace();
            return null;
        }
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public enum HTTPRequestType {
    GET("GET"),
    POST("POST");
 
    private String title;
 
    HTTPRequestType(String title) {
        this.title = title;
    }
 
    public String getTitle() {
        return title;
    }
 
    @Override
    public String toString() {
        return this.getTitle();
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Pair<L, R> {
    private final L left;
    private final R right;
 
    public Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }
 
    public L getLeft() {
        return left;
    }
    public R getRight() {
        return right;
    }
 
    @Override
    public int hashCode() {
        return left.hashCode() ^ right.hashCode();
    }
 
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) return false;
        Pair pairo = (Pair) o;
        return this.left.equals(pairo.getLeft()) &&
                this.right.equals(pairo.getRight());
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class GetYMetrics {
    protected final DownloadWebService dws = new DownloadWebService();
    protected final String token = "AgAAAAAUI50UAAXb-rzOPxeSKkoEiWvWngt_GCU"; // token: AgAAAAAUI50UAAXb-rzOPxeSKkoEiWvWngt_GCU
 
    // url: https://api-metrika.yandex.ru/management/v1/counter/{counter}/logrequests
    // https://api-metrika.yandex.ru/management/v1/counter/",counter,"/logrequests?date1=",date.from,"&date2=",date.to,"&fields=",fields,"&source=",source
    public void getYMetric(String url, String counter, LocalDate dFrom, LocalDate dTo, String fields, String source){
        counter = counter == null ? "52380802" : counter;
        url = url == null
                ? "https://api-metrika.yandex.ru/management/v1/counter/{counter}/logrequests".replace("{counter}", counter)
                : url;
        final LocalDate dFromF = dFrom == null ? LocalDate.now().plusDays(-10) : dFrom;
        final LocalDate dToF = dTo == null ? LocalDate.now().plusDays(-1) : dTo;
        final String fieldsF = fields == null
                ? "ym:s:date,ym:s:counterID,ym:s:dateTime,ym:s:isNewUser,ym:s:startURL,ym:s:visitDuration,ym:s:ipAddress,ym:s:referer"
                : fields;
        final String sourceF = source == null ? "visits" : source;
 
        try {
            String argumentedUrl = dws.createArgumentedUrl(url
                    , Arrays.asList(
                            new Pair<>("date1", dFromF.toString())
                            , new Pair<>("date2", dToF.toString())
                            , new Pair<>("fields", fieldsF)
                            , new Pair<>("source", sourceF)
                    )
            );
            System.out.println(argumentedUrl);
            //String res = dws.sendGet(
            String res = dws.sendPost(argumentedUrl
                    , Arrays.asList(
                            new Pair<>("Host", "api-metrika.yandex.net")
                            , new Pair<>("Authorization", "OAuth " + token)
                            , new Pair<>("Content-Type", "application/x-yametrika+json")
                    )
            );
            System.out.println(res);
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }
}
Добавлено через 17 секунд
Но это уже совсем другая история.
0
 Аватар для Goongala
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,027
Записей в блоге: 2
11.10.2019, 17:44
Цитата Сообщение от Vhodnoylogin Посмотреть сообщение
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public enum HTTPRequestType {
 GET("GET"),
 POST("POST");
private String title;
HTTPRequestType(String title) {
 this.title = title;
 }
public String getTitle() {
 return title;
 }
@Override
 public String toString() {
 return this.getTitle();
 }
}
шоб вы знали, перечисления по дефолту через toString возвращают своё имя

Java
1
2
3
4
5
6
7
public class MyClass {
    public static void main(String args[]) {
      System.out.println(Gaga.Lala);
    }
}
 
enum Gaga { Lala, Tata }
Bash
1
Lala
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
11.10.2019, 22:36
К чему такие сложности? И нафига столько заголовков? Имхо пойдет минимум заголовков, это токен и тип контента для гет, а для пост еще длинну контента (длинна байт от тела). Тело пост запроса передается в стрим соединения и у вас пост не пройдет, там надо устанавливать метод дуаутпут в тру. Вы ведь не браузер эмулируете, остальные заголовки лишние.
Да и думаю и гет и пост тоже в данном случае излишне, я только с апи переводчика имел дело и там гет/пост делали одно и тоже, только у гет все параметры в адресе а у пост в теле (со всеми плюсами и минусами вытекающими).
А вообще стоит сделать один метод принимающий токен, адрес и тело запроса в случае пост и возвращающее строку json ответ. И строку парсить уже вне. Чуть позже могу накидать код.
Токен не советовал бы светить, советую модератору стереть в коде его, это инфа не для чужих глаз.

Добавлено через 3 часа 30 минут
Вот здесь имеет место делать отдельный метод для соединения, так как ему передаются параметры
Столько заголовков имелось в виду что зачем делать спец обработку? Если можно послать только нужное и не заморачиваться
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
 
public class Yandex {
    //----vvv
    public static void main(String[] args) {
        new Yandex();
    }
    
    private Yandex() {
        String fields = "ym:s:date,ym:s:counterID,ym:s:dateTime,ym:s:isNewUser,"
                + "ym:s:startURL,ym:s:visitDuration,ym:s:ipAddress,ym:s:referer";
        System.out.println(getResponseString("52380802", "2019-10-01", "2019-10-10", fields, "visits"));
    }
    //код выше для демонтсрации работы, чтобы запускать класс без других
    //----^^^
    public String getResponseString(String counter, String date1, String date2, String fields, String source) {
        String url = buildURL(counter, date1, date2, fields, source);
        return getResponse(url);
    }
    
    private String buildURL(String counter, String date1, String date2, String fields, String source) {
        String baseURL = "https://api-metrika.yandex.net/management/v1/counter/";
        return String.format("%s%s/logrequests?date1=%s&date2=%s&fields=%s&source=%s", baseURL, counter, date1, date2, fields, source);
    }
    
    private String getResponse(String url) {
        String token = ""; //place token here
        try {
            HttpsURLConnection connection = connect(url);
            connection.setRequestProperty("Content-Type", "application/x-yametrika+json");
            connection.setRequestProperty("Authorization", "OAuth " + token);
            //connection.setRequestMethod("POST"); //если не будет работать
            if (connection.getResponseCode() == 200) {
                return inputstreamToString(connection.getInputStream());
                //return IOUtils.toString(inputStream, StandardCharsets.UTF_8); //if use Apache Commons
            } else {
                System.out.println("Response code: " + connection.getResponseCode());
                return "Error1";
            }
        } catch (NoSuchAlgorithmException | KeyManagementException | IOException e) {
            e.printStackTrace();
            return "Error2";
        }
    }
    
    private String inputstreamToString(InputStream is) throws IOException {
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }
        return result.toString("UTF-8");
    }
    
    private HttpsURLConnection connect(String urlstr) throws NoSuchAlgorithmException, KeyManagementException, IOException {
        String hostname = "bcpsg-moscow.headoffice.psbank.local";
        int port = 8080;
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port));
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        } };
        SSLContext sc = SSLContext.getInstance("SSL"); 
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection connection =  (HttpsURLConnection)(new URL(urlstr).openConnection(proxy));
        connection.setSSLSocketFactory(sc.getSocketFactory());
        connection.setHostnameVerifier((hostname1, session) -> true);
        return connection;
    }
 
}
Код ниже изменил, так как первый вариант все запросы меняет и вызывать его стоит один раз, а второй меняет только конкретный запрос. То есть при использовании первого будет у всех запросов в программе отключена проверка а у второго только у этого конкретного запроса.
Java
1
2
3
4
5
HttpsURLConnection.setDefaultSSLSocketFactory();
HttpsURLConnection.setDefaultHostnameVerifier();
//заменил на
connection.setSSLSocketFactory();
connection.setHostnameVerifier();
Десериализацию json не понял что у вас, можете использовать свою, или потом обратиться за советом, но показав структуру json.
Я не умею и не люблю использовать всякие лямбды и стримы. Мне понятней и приятней функциональное программирование из чистого Си. Весь код пишу в этом духе.
если надо передать полноценный пост запрос то надо добавить
Java
1
2
3
4
byte out[] = "".getBytes();
connection.setDoInput(true);
connection.setRequestProperty("Content-Length", out.length + "");
connection.getOutputStream().write(out);
заменив "" на данные для передачи типа String
А так по сути это get запрос, ведь у post обычно есть тело (код чуть выше). На сайте яндекса нашел опечатки, так что возможно и это тоже.
get запрос это когда все передаваемые данные на сервер в адресе
post запрос это обычно короткий адрес и все данные в теле запроса после заголовков.
И у вас в коде не тот адрес, нужен этот api-metrika.yandex.net (по крайней мере везде в описании апи он)
0
-12 / 3 / 0
Регистрация: 02.04.2012
Сообщений: 347
11.10.2019, 23:17  [ТС]
На самом деле я написал тот пост больше "для себя", чтобы вынести код за пределы рабочего компа. Если бы скинул письмом себе на почту - меня бы поругали. А так - никто не обратит внимания. А настоящего хищения я не произвожу.

Не ожидал получить столько ответов. Буду смотреть на чужой код - разбираться, как можно улучшить свою прогу.

Добавлено через 4 минуты
Цитата Сообщение от alecss131 Посмотреть сообщение
Токен не советовал бы светить, советую модератору стереть в коде его, это инфа не для чужих глаз.
Это временный токен, который удалится вместе с приложением, которое было создано на прошлой неделе только ради того, чтобы попробовать авторизоваться в Я.метриках.
А вот counter я бы попросил удалить.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.10.2019, 23:17
Помогаю со студенческими работами здесь

Написание прокси сервера на сокетах. Проброс сообщений основному серверу и возврат значений через прокси
Есть 3 приложения. 1. Клиент. 2. Прокси сервер. 3. Сервер. Что задумано: Запускается клиент и получает параметры конфигурации с...

Не достучаться до оборудования, подключенного через 3G модем
Здравствуйте, есть роутер zyxel keenetic 4g, выход в интернет через 3G модем МегаФон E367, сигнал 3G стабильный (подключена внешняя...

Не могу достучаться до лога через контекст сервлета
Есть сервлет, а к нему фильтр, в фильтре пытаюсь написать хоть что-то в лог. В режиме отладки я вижу что doFilter вызываеться так что...

Как достучаться до псевдоэлемента через потомка (использование hover)?
Добрый день Уважаемые, есть блок, при наведении на который должно всплывать окошко созданное через css 3 и псевдоэлемент. Вот структура: ...

Конфигурация cisco: достучаться через циску другого второстепенного сервера
всем привет!!! Такая ситуация:есть 3 сервера,3 циски, находятся в разных городах. Все циски связаны между собой,и каждая связана со своим...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru