Форум программистов, компьютерный форум, киберфорум
Программирование Android
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/49: Рейтинг темы: голосов - 49, средняя оценка - 4.94
 Аватар для Bes-s
31 / 31 / 0
Регистрация: 05.11.2011
Сообщений: 178

Получение JSON с https сервера

25.06.2012, 16:27. Показов 9983. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Стоит задача: получить с сервера данные в JSON формате. На сервере используется Basic Authentication. Логин пароль нужно передавать у формате: Логин:Пароль.
А также url сервера отдает неподписанные сертификаты.
Проблема в том, что я не смог найти способа игнорировать проверку сертификатов. Делаю это так:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {}
но тогда проверка не вырубается для HttpGet... и тут я несколько не понимаю как можно получить JSON без гета...

еще проблема: авторизуюсь таким образом:
Java
1
2
3
4
5
6
URL url = new URL(tasklist);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            String temps = new String(edLog.getText().toString()+":"+edPass.getText().toString());
            c.setRequestProperty("Authorization", "basic " + Base64.encode(temps.getBytes(),0));
            c.setUseCaches(false);
            c.connect();
но сначала получал от сервера OK в реквесте, независимо от введенных данных... затем только bad request...

полностью запутался в этой теме. раньше с таким не сталкивался... объясните, или помогите линком на какой нибудь толковый ман, с таким же механизмом получения JSON с сервера...
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.06.2012, 16:27
Ответы с готовыми решениями:

Получение JSON с сервера
Есть класс который принимает строку URL и возвращает JSONObject public class Json { public static JSONObject getJson(String...

Не могу получить json по https
Доброго времени суток не могу получить json по https коннект проходит package com.devcolibri.parser; import...

Https соединение с сертфикатам пользователя и сервера
Добрый день. Есть следующая ситуация. Есть сервер, у него есть свой сертификат. Есть клиент, у него свой сертификат. Заходя через браузер...

15
Novatom
26.06.2012, 12:46
Привет.

Вот тут написано, как добавить сертификат в доверенные. При запросе данных с сервера используешь MyHttpClient - с ним работаешь как с обычным get/post запросами. Всё работает, будут вопросы - спрашивай, постараюсь помочь.
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
28.06.2012, 02:36
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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
 
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
 
public String executeHttpsGet(String uri) {
            Log. v(LOG_TAG, "Https request -" + uri);
            String strResponse = null;
            BufferedReader reader = null;
             try {
                   // Create a trust manager that does not validate certificate chains
                   final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
 
                         @Override
                         public void checkClientTrusted(
                                    java.security.cert.X509Certificate[] chain,
                                    String authType) throws CertificateException {
                               // TODO Auto-generated method stub
 
                        }
 
                         @Override
                         public void checkServerTrusted(
                                    java.security.cert.X509Certificate[] chain,
                                    String authType) throws CertificateException {
                               // TODO Auto-generated method stub
 
                        }
 
                         @Override
                         public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                               // TODO Auto-generated method stub
                               return null ;
                        }
 
                  } };
 
                   // Install the all-trusting trust manager
                   final SSLContext sslContext = SSLContext.getInstance("SSL");
                  sslContext.init( null, trustAllCerts,
                               new java.security.SecureRandom());
                   // Create an ssl socket factory with our all-trusting manager
                   final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext
                              .getSocketFactory();
 
                   // All set up, we can get a resource through https now:
                   final URLConnection connection = new URL(uri).openConnection();
                   // Tell the url connection object to use our socket factory which
                   // bypasses security checks
                  ((HttpsURLConnection) connection)
                              .setSSLSocketFactory(sslSocketFactory);
 
                  reader = new BufferedReader(new InputStreamReader(
                              connection.getInputStream()));
 
                  StringBuffer sb = new StringBuffer("" );
                  String line = "";
                   while ((line = reader.readLine()) != null) {
                        sb.append(line);
                  }
                  strResponse = sb.toString();
                  Log. v(LOG_TAG, "response - " + strResponse);
 
            } catch (final Exception e) {
                  Log. v(LOG_TAG, "HttpsGet failed");
                  e.printStackTrace();
            } finally {
                   if (reader != null) {
                         try {
                              reader.close();
                        } catch (IOException e) {
                              e.printStackTrace();
                        }
                  }
            }
 
             return strResponse;
      }
1
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
06.09.2012, 14:50
Требуется решить ту же задачу - получить Json от https-сервера.
Материала что-то много не нашел. А приведенный тут код мне не совсем понятен.

Разъясните, пожалуйста, по порядку все шаги (желательно с кодом, раздельно по шагам) для работы с https и последующим выполнением get-запросов для получения Json.

Спасибо
0
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
06.09.2012, 17:40
executeHttpsGet запихаете url, получаете строку. что не понятно?
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
06.09.2012, 18:03
Запихать url в функу и получить результат - понятно.

Я хочу понять какие шаги необходимы и для чего. И какая строчка кода для чего нужна.

Хотя бы потому, что на строке

reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));

отбиваетс с "Hostname "xxxxxx" was not verified"

Понимаю, что это связано с сертификатом и, вероятно, он является неизвестным и его как-то надо установить или подвердить... Как?
0
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
06.09.2012, 21:07
у меня все работает как есть без установки сертификатов. именно для этого и искал эту функцию.

Добавлено через 1 минуту
а с установленными сертификатами должны работать обычные запросы без всего этого.

Добавлено через 4 минуты
а с браузера отправить запрос пробовали? работает?
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
06.09.2012, 22:29
Сертификат неизвестного издателя и с несоответствием с адресом страницы, потому, видимо и ругается.
Временно обошел костылем (украдено откуда-то)
Java
1
2
3
if (connection instanceof HttpsURLConnection) {
  ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
}
Таким образом получается, что он игнорит вообще сертификаты и проходит.
Однако на моменте
Java
1
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
вылетает теперь с java.io.FileNotFoundException.

Браузер на строку подключения ругается на сертификат, что тот неизвестный и не для этого сайта, жмешь "пофиг", он запрашивает имя пользователя и пароль и далее отдает Json-ответ (Chrome его прям и пишет).


Вот потому я и спрашиваю, какая последовательность должна быть в коде? Где указывать имя пользователя и пароль?

Пробовал добавлять setRequestProperty, как написано у Bes-s, но ничего не меняется - так же FileNotFoundException
0
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
06.09.2012, 22:55
имя пользователя и пароль видимо должен быть в том же реквесте, иногда они идут в первом реквесте который дает некую id, и по ней делаются остальные реквесты.
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
07.09.2012, 10:02
А что значит "должен быть в реквесте"? В каком свойстве? Прописывание setRequestProperty не дает никакого результата. Точнее результат одинаковый, что со свойством "Authorization", что без него.
0
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
07.09.2012, 21:15
это нужно читать в документации службы которой вы эти реквесты посылаете.
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
08.09.2012, 19:21
Итак, покопался, поразбирался...
Вот чего собственно я хотел узнать, чтобы мне объяснили по шагам (разобрался сам, может кому пригодится):
1. Нам необходимо получить ответ от сервера с HTTPS с HTTP авторизацией. Это два раздельных процесса (моя ошибка и заключалась в том, что предположил это цельным процессом).
2. Соответственно необходимо проити проверку сертификата
3. Проверить имя хоста
4. Организовать авторизацию.

Итак, для этого...

5. Для проверки сертификата имеется множество способов, один из них приведен в примере. Вот кусок кода который отвечает за проверку:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
final TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        publishProgress("getAcceptedIssuers");
         return null;
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        publishProgress("Сведения о сертификате : " + chain[0].getIssuerX500Principal().getName() + "\n Тип авторизации : " + authType);
    }
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        publishProgress("checkClientTrusted : " + authType);
    }
} };
Этот кусок кода создает массив менеджеров проверки сертификатов и добавляет в него одну реализацию интерфейса проверки сертификата X509TrustManager. Добавлять необходимо все три метода интерфейса, хотя используется в нашем случае только один - checkServerTrusted. В нем мы можем провести проверку сертификата. Если сертификат нормальный, то метод ничего не делает (как у нас и есть), а если сертификат "плохой", то необходимо генерировать исключение (правильнее всего - CertificateException).

Видимо на этом месте барузеры проводят проверку сертификатов на надежные источники и т.п. И в том числе выдают сообщение "Сертификат безопасности этого веб-узла не был выпущен доверенным центром сертификации."

Далее получаем SSLContext и настраиваем его с помощью нашего массива менеджеров trustAllCerts. А так же получаем SSLSocketFactory.
Java
1
2
3
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init( null, trustAllCerts, new java.security.SecureRandom());
final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
Детально для чего и как работает вся эта конструкция я еще не разобрался, но предполагаю, что собственно это и есть классы отвечающие за создание всех объектов, проверяющих сертификаты и выполняющий все методы по созданию защищенного соединения, в том числе шифрования.

6. Создаем объект коннекта
Java
1
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
И назначаем ему ранее полученный sslSocketFactory
Java
1
((HttpsURLConnection) conn).setSSLSocketFactory(sslSocketFactory);
Собственно теперь у нас есть настроеный HttpsURLConnection, который имеет фабрику SSL-сокетов для организации соединения и подключеный trustAllCerts (массив менеджеров для проверки сертификатов с созданым объектом, который и будет проверять сертификат)

Можно было бы выполнять запрос, однако у меня он далее и отбивался с оибкой "Hostname "xxxxxx" was not verified"

7. А вот для этого для мы добавляем к нашему HttpsUrlConnection-у проверку имени хоста
Java
1
2
3
4
5
((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String arg0, SSLSession arg1) {
        return true;
    }
});
В данном случае проверку не делаем, а подтверждаем любой хост. А можно было бы проверять на соответсвие чему-нибудь. В частности, видимо именно подобной операцией браузер проверяет соответствие сертификата и Хоста и выдает мне сообщение "Сертификат безопасности этого веб-узла был выпущен для веб-узла с другим адресом"

8. Далее настраиваем свойства коннекта
Java
1
2
3
4
5
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setReadTimeout(10000 );
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
Таймаут-ы можно не прописывать, однако в случае каких-либо проблем со связью висеть может весьма долго.
Так же как и выставление DoInput подразумевает операцию GET. Хотя я предпочитаю явно прописывать все то, что должно быть явным.

9. И вот момент указания HTTP-авторизации
Java
1
conn.setRequestProperty("Authorization", "Basic " + token);
К HTTPS-у данная операция отношения не имеет. По сути требовать авторизацию может и простой HTTP-сервер. Типов HTTP-авторизации несколько основные - Basic и Digest. В простейшем случае используется Basic, Digest - применяет некие способы шифрования.

token - логин+пароль в виде "loginassword" переведенный в последовательность байт в формате Base64. Это делается с помощью
Java
1
byte[] enc = Base64.encode("www:www".getBytes("UTF16"), Base64.DEFAULT);
Однако enc - это массив байт, а в свойство надо передавать String. И вот тут я долго воевал. Ибо приведенные везде приемы типа
Java
1
String token = enc.toString();
или просто прибавления enc к строке не работало. Как оказалось этот toString() отдает неправильное представление. Как раз на этом я и бился долго.

Случайно наткнулся на это несоответствие, поискал в интернете и нашел функцию. которая адекватно переводит в Base64-строку
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
    static final char base64Array [] = {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
        'w', 'x', 'y', 'z', '0', '1', '2', '3',
        '4', '5', '6', '7', '8', '9', '+', '/'
    };
 
    private static String base64Encode (String string)    {
      String encodedString = "";
      byte bytes [] = string.getBytes ();
      int i = 0;
      int pad = 0;
      while (i < bytes.length) {
        byte b1 = bytes [i++];
        byte b2;
        byte b3;
        if (i >= bytes.length) {
           b2 = 0;
           b3 = 0;
           pad = 2;
           }
        else {
           b2 = bytes [i++];
           if (i >= bytes.length) {
              b3 = 0;
              pad = 1;
              }
           else
              b3 = bytes [i++];
           }
        byte c1 = (byte)(b1 >> 2);
        byte c2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
        byte c3 = (byte)(((b2 & 0xf) << 2) | (b3 >> 6));
        byte c4 = (byte)(b3 & 0x3f);
        encodedString += base64Array [c1];
        encodedString += base64Array [c2];
        switch (pad) {
         case 0:
           encodedString += base64Array [c3];
           encodedString += base64Array [c4];
           break;
         case 1:
           encodedString += base64Array [c3];
           encodedString += "=";
           break;
         case 2:
           encodedString += "==";
           break;
         }
        }
        return encodedString;
    }
Вероятно, я чего-то недогоняю с классом Base64. Подскажите где ошибка. С приведенной выше функцией все заработало.

10. Ну и собственно момент подключения. В отличие от ранее приведенного примера, где сразу производится попытка чтения из потока, правильнее выполнять код, по проверке состояния ответа (response)
Java
1
2
3
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
    throw new Exception("http error : " + conn.getResponseCode());
}
Вот как раз моя ошибка на попытке обращении к потоку (FileNotFoundException) была следствием отсутствия потока, ввиду того, что в ответе response была та или иная HTTP-ошибка. Например, если убрать добавление свойтсва авторизации к HttpsURLConnection, сервер возвращает 401 - требуется авторизация, 403 - в случае ошибки авторизации и т.п.
В данном обработчике можно поставить соответствующую реакцию на ответ сервера

11. Ну и если ответ сервера все же HTTP_OK, то можно обрабатывать результат приведенным в примере способом
Java
1
2
3
4
5
6
7
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String nextLine = null;
while ((nextLine = in.readLine()) != null) {
    sb.append(nextLine);
}
in.close();
conn.disconnect();
Все, данные получены!

Это чисто моё изучение материала. Однако решил сюда написать, потому как подробно по шагам, что для чего... Такого описания я так нигде и не нашел. Может кому пригодится еще.

Если где ошибся - поправьте, может и дополните чем полезным
3
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
08.09.2012, 20:39
О, да вы целый гайд написали. Подредактируйте и можете на хабре постить. Первая поправка - "6. Создаем объект коннекта" здесь мы еще и открываем конекшин.
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
08.09.2012, 21:42
Спасибо! Возможно и напишу на Хабре. Не разу этого не делал
Цитата Сообщение от V0v1k Посмотреть сообщение
Первая поправка - "6. Создаем объект коннекта" здесь мы еще и открываем конекшин.
Теоретически - да. Однако реальный коннект происходит только при выполнении команд работы с результатом (Response). Потому для себя я воспринимаю данную операцию именно как создание объекта Коннешена, а не как его открытие. Хотя, возможно, Андроид действительно выполняет какие-то системные действия и выделение ресурса под Коннекшн. Тогда это будет открытием.
0
1162 / 986 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
08.09.2012, 22:45
там же вызывается метод openConnection, что тут еще думать)
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
08.09.2012, 23:01
И да, вот еще случайно заметил...
Java
1
byte[] enc = Base64.encode("www:www".getBytes("UTF16"), Base64.DEFAULT);
.getBytes("UTF16") - UTF16 не обязательно, это осталось от экспериментов. Точнее, я даже не знаю как должно быть, потому как не заработало ни в каких вариантах кодировки.

Кто в курсе, подскажите как правильнее штатными средствами переводить текст в текстовое представление Base64.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.09.2012, 23:01
Помогаю со студенческими работами здесь

Получение ответа в формате json
пытаюсь получить ответ в формате json от моего php скрипта и разобрать его. В общих чертах: new...

Отправка и получение картинок JSON
Всем привет, может кто подскажет простой пример того, как: 1 преобразовать Bitmap изображение и кинуть его на сервер 2 имея ссылку с...

Парсинг JSON ответа от сервера
Здравствуйте друзья, давно не заходил к вам в гости. Столкнулся с таким интересным (интересно построенным) ответом от сервера в формате...

Получение json строки и ее вывод в консоль
Доброго времени суток. Знаю, что в интернете полно ресурсов на тему json, но не могу найти объяснения, как оно полностью работает. Я...

Как правильно парсить json с сервера
Здравствуйте. У меня есть JSON, полученный с сервера, имеет приблизительно такой вид: В приложении будет два таба, в...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru