diff --git a/README.md b/README.md index da33d28..c00a5cb 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,14 @@ TODO: Можно показать пример поискового запрос ``` ## Digest-аутентификация +Параметры Digest-аутентификации можно передать через свойство `ДополнительныеПараметры.Аутентификация`. +При этом `Тип` нужно установить в значение `Digest`. +```bsl +Аутентификация = Новый Структура("Пользователь, Пароль, Тип", "user", "pass", "Digest"); +Результат = КоннекторHTTP.GetJson( + "https://httpbin.org/digest-auth/auth/user/pass",, + Новый Структура("Аутентификация", Аутентификация)); +``` ## Errors and Exceptions diff --git a/src/CommonModules/КоннекторHTTP/Ext/Module.bsl b/src/CommonModules/КоннекторHTTP/Ext/Module.bsl index 5189b2d..cd731fb 100644 --- a/src/CommonModules/КоннекторHTTP/Ext/Module.bsl +++ b/src/CommonModules/КоннекторHTTP/Ext/Module.bsl @@ -725,13 +725,18 @@ КонецФункции +Функция ОтправитьHTTPЗапрос(Сессия, ПодготовленныйЗапрос, Настройки) + + Соединение = ПолучитьСоединение( + РазобратьURL(ПодготовленныйЗапрос.URL), ПодготовленныйЗапрос.Аутентификация, Настройки); + Возврат Соединение.ВызватьHTTPМетод(ПодготовленныйЗапрос.Метод, ПодготовленныйЗапрос.HTTPЗапрос); + +КонецФункции + Функция ОтправитьЗапрос(Сессия, ПодготовленныйЗапрос, Настройки) Начало = ТекущаяУниверсальнаяДатаВМиллисекундах(); - Соединение = ПолучитьСоединение( - РазобратьURL(ПодготовленныйЗапрос.URL), ПодготовленныйЗапрос.Аутентификация, Настройки); - Ответ = Соединение.ВызватьHTTPМетод(ПодготовленныйЗапрос.Метод, ПодготовленныйЗапрос.HTTPЗапрос); - + Ответ = ОтправитьHTTPЗапрос(Сессия, ПодготовленныйЗапрос, Настройки); Для Каждого Обработчик Из ПодготовленныйЗапрос.СобытияНаОтвет Цикл Если Обработчик = "ОбработкаОтветаСКодом401" Тогда ОбработкаОтветаСКодом401(Сессия, ПодготовленныйЗапрос, Настройки, Ответ); @@ -1433,7 +1438,6 @@ КонецЕсли; Если Ответ.КодСостояния < 400 ИЛИ Ответ.КодСостояния >= 500 Тогда - // TODO: Здесь нужно что-то сделать Возврат; КонецЕсли; @@ -1449,24 +1453,112 @@ КлючЗначение = СтрРазделить(Часть, "="); ПараметрыDigest.Вставить(КлючЗначение[0], КлючЗначение[1]); КонецЦикла; + // TODO: Видимо ПараметрыDigest нужно сохранять в сессии, чтобы счетчик сообщений работал корректно ПодготовленныйЗапрос.Вставить("ПараметрыDigest", ПараметрыDigest); ПодготовленныйЗапрос.Заголовки.Вставить("Authorization", ПодготовитьЗаголовокDigest(ПодготовленныйЗапрос)); ПодготовленныйЗапрос.HTTPЗапрос.Заголовки = ПодготовленныйЗапрос.Заголовки; - ОтправитьЗапрос(Сессия, ПодготовленныйЗапрос, Настройки); - Возврат; + Ответ = ОтправитьHTTPЗапрос(Сессия, ПодготовленныйЗапрос, Настройки); КонецЕсли; КонецПроцедуры +Функция ОпределитьХешФункцию(Знач Алгоритм) + + Алгоритм = ВРег(Алгоритм); + Если Не ЗначениеЗаполнено(Алгоритм) ИЛИ Алгоритм = "MD5" ИЛИ Алгоритм = "MD5-SESS" Тогда + Возврат ХешФункция.MD5; + ИначеЕсли Алгоритм = "SHA" Тогда + Возврат ХешФункция.SHA1; + ИначеЕсли Алгоритм = "SHA-256" Тогда + Возврат ХешФункция.SHA256; + Иначе + Возврат Неопределено; + КонецЕсли; + +КонецФункции + Функция ПодготовитьЗаголовокDigest(ПодготовленныйЗапрос) - Заголовок = ""; + Алгоритм = ОпределитьХешФункцию(ПодготовленныйЗапрос.ПараметрыDigest.algorithm); + АлгоритмСтрокой = ВРег(ПодготовленныйЗапрос.ПараметрыDigest.algorithm); + Если Алгоритм = Неопределено Тогда + Возврат Неопределено; + КонецЕсли; - // TODO: Сделать вычисление DIGEST + СтруктураURL = РазобратьURL(ПодготовленныйЗапрос.URL); + Путь = СтруктураURL.Путь; + Если ЗначениеЗаполнено(СтруктураURL.ПараметрыЗапроса) Тогда + Путь = Путь + "?" + КодироватьПараметрыЗапроса(СтруктураURL.ПараметрыЗапроса); + КонецЕсли; - Возврат Заголовок; + A1 = СтрШаблон("%1:%2:%3", + ПодготовленныйЗапрос.Аутентификация.Пользователь, + ПодготовленныйЗапрос.ПараметрыDigest.realm, + ПодготовленныйЗапрос.Аутентификация.Пароль); + A2 = СтрШаблон("%1:%2", ПодготовленныйЗапрос.Метод, Путь); + + HA1 = ХешированиеСтроки(Алгоритм, A1); + HA2 = ХешированиеСтроки(Алгоритм, A2); + + Если Не ПодготовленныйЗапрос.ПараметрыDigest.Свойство("last_nonce") Тогда + ПодготовленныйЗапрос.ПараметрыDigest.Вставить("last_nonce"); + КонецЕсли; + + Если ПодготовленныйЗапрос.ПараметрыDigest.nonce = ПодготовленныйЗапрос.ПараметрыDigest.last_nonce Тогда + ПодготовленныйЗапрос.ПараметрыDigest.nonce_count = ПодготовленныйЗапрос.ПараметрыDigest.nonce_count + 1; + Иначе + ПодготовленныйЗапрос.ПараметрыDigest.Вставить("nonce_count", 1); + КонецЕсли; + + ncvalue = Формат(ПодготовленныйЗапрос.ПараметрыDigest.nonce_count, "ЧЦ=8; ЧВН=; ЧГ="); + cnonce = Лев(СтрЗаменить(НРег(Новый УникальныйИдентификатор), "-", ""), 16); + + Если АлгоритмСтрокой = "MD5-SESS" Тогда + HA1 = ХешированиеСтроки(Алгоритм, СтрШаблон("%1:%2:%3", HA1, ПодготовленныйЗапрос.ПараметрыDigest.nonce, cnonce)); + КонецЕсли; + + Если Не ЗначениеЗаполнено(ПодготовленныйЗапрос.ПараметрыDigest.qop) Тогда + respdig = ХешированиеСтроки(Алгоритм, СтрШаблон("%1:%2:%3", HA1, ПодготовленныйЗапрос.ПараметрыDigest.nonce, HA2)); + ИначеЕсли ПодготовленныйЗапрос.ПараметрыDigest.qop = "auth" + ИЛИ СтрРазделить(ПодготовленныйЗапрос.ПараметрыDigest.qop, ",", Ложь).Найти("auth") <> Неопределено Тогда + noncebit = СтрШаблон("%1:%2:%3:%4:%5", ПодготовленныйЗапрос.ПараметрыDigest.nonce, ncvalue, cnonce, "auth", HA2); + respdig = ХешированиеСтроки(Алгоритм, СтрШаблон("%1:%2", HA1, noncebit)); + Иначе + // INFO: auth-int не реализовано + Возврат Неопределено; + КонецЕсли; + + ПодготовленныйЗапрос.ПараметрыDigest.last_nonce = ПодготовленныйЗапрос.ПараметрыDigest.nonce; + + base = СтрШаблон("username=""%1"", realm=""%2"", nonce=""%3"", uri=""%4"", response=""%5""", + ПодготовленныйЗапрос.Аутентификация.Пользователь, + ПодготовленныйЗапрос.ПараметрыDigest.realm, + ПодготовленныйЗапрос.ПараметрыDigest.nonce, + Путь, + respdig); + + Если ЗначениеЗаполнено(ПодготовленныйЗапрос.ПараметрыDigest.opaque) Тогда + base = base + СтрШаблон(", opaque=""%1""", ПодготовленныйЗапрос.ПараметрыDigest.opaque); + КонецЕсли; + Если ЗначениеЗаполнено(ПодготовленныйЗапрос.ПараметрыDigest.algorithm) Тогда + base = base + СтрШаблон(", algorithm=""%1""", ПодготовленныйЗапрос.ПараметрыDigest.algorithm); + КонецЕсли; + Если ЗначениеЗаполнено(ПодготовленныйЗапрос.ПараметрыDigest.qop) Тогда + base = base + СтрШаблон(", qop=""auth"", nc=%1, cnonce=""%2""", ncvalue, cnonce); + КонецЕсли; + + Возврат СтрШаблон("Digest %1", base); + +КонецФункции + +Функция ХешированиеСтроки(Алгоритм, Строка) + + ХешированиеДанных = Новый ХешированиеДанных(Алгоритм); + ХешированиеДанных.Добавить(Строка); + + Возврат СтрЗаменить(НРег(ХешированиеДанных.ХешСумма), " ", ""); КонецФункции @@ -1480,7 +1572,7 @@ Прервать; КонецЕсли; - ПерваяЧасть = Лев(Строка, Позиция - СтрДлина(Разделитель)); + ПерваяЧасть = Лев(Строка, Позиция - СтрДлина(Разделитель) + 1); Результат.Добавить(ПерваяЧасть); Строка = Сред(Строка, Позиция + СтрДлина(Разделитель)); КонецЦикла; diff --git a/src/ConfigDumpInfo.xml b/src/ConfigDumpInfo.xml index 10d1ade..955cd65 100644 --- a/src/ConfigDumpInfo.xml +++ b/src/ConfigDumpInfo.xml @@ -1,16 +1,16 @@  - - + + - + - + \ No newline at end of file