1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2026-06-12 00:34:16 +02:00

S3: Авторизация

This commit is contained in:
Anton Titovets
2024-11-12 11:19:30 +03:00
parent 96adb4125c
commit 6feee6d278
6 changed files with 5939 additions and 5467 deletions
+5493 -5453
View File
File diff suppressed because it is too large Load Diff
+203 -6
View File
@@ -45,10 +45,15 @@
#Область ОбщиеМетоды
Функция ПолучитьСтруктуруАвторизации(Знач AccessKey, Знач SecretKey, Знач Region, Знач URL, Знач Service = "s3") Экспорт
КлючПодписи = ПолучитьКлючПодписи(SecretKey, Region, Service);
Функция ПолучитьСтруктуруАвторизации(Знач AccessKey, Знач SecretKey, Знач Region, Знач Service = "s3") Экспорт
СтруктураАвторизации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("AccessKey", AccessKey, "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("SecretKey", SecretKey, "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("Region" , Region , "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("Service" , Service , "Строка", СтруктураАвторизации);
Возврат СтруктураАвторизации;
КонецФункции
@@ -66,9 +71,50 @@
#Область СлужебныеПроцедурыИФункции
Функция ПолучитьКлючПодписи(Знач СекретныйКлюч, Знач Регион, Знач Сервис)
Функция СоздатьЗаголовокАвторизации(Знач СтруктураДанных, Знач Запрос, Знач Соединение, Знач Метод)
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СтруктураДанных);
Если ТипЗнч(СтруктураДанных) = Тип("Массив") Тогда
ВызватьИсключение "Ошибка получения авторизационных данных из структуры";
КонецЕсли;
МассивНеобходимыхПолей = Новый Массив;
МассивНеобходимыхПолей.Добавить("AccessKey");
МассивНеобходимыхПолей.Добавить("SecretKey");
МассивНеобходимыхПолей.Добавить("Region");
МассивНеобходимыхПолей.Добавить("Service");
ОтсутствующиеПоля = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(СтруктураДанных, МассивНеобходимыхПолей);
Если ОтсутствующиеПоля.Количество() > 0 Тогда
ВызватьИсключение "Отсутствуют необходимые данные авторизации: " + СтрСоединить(ОтсутствующиеПоля, ", ");
КонецЕсли;
AccessKey = СтруктураДанных["AccessKey"];
SecretKey = СтруктураДанных["SecretKey"];
Region = СтруктураДанных["Region"];
Service = СтруктураДанных["Service"];
ТекущаяДата = OPI_Инструменты.ПолучитьТекущуюДату();
КлючПодписи = ПолучитьКлючПодписи(SecretKey, Region, Service, ТекущаяДата);
КаноническийЗапрос = СоздатьКаноническийЗапрос(Запрос, Соединение, Метод);
Скоуп = СоздатьСкоуп(Region, Service, ТекущаяДата);
СтрокаДляПодписи = СоздатьСтрокуПодписи(КаноническийЗапрос, Скоуп, ТекущаяДата);
Сигнатура = OPI_Криптография.HMACSHA256(КлючПодписи, СтрокаДляПодписи);
Сигнатура = ПолучитьHexСтрокуИзДвоичныхДанных(Сигнатура);
КлючиЗаголовков = ПолучитьСтрокуКлючейЗаголовков(Запрос);
ЗаголовокАвторизации = СформироватьЗаголовокАвторизации(AccessKey, Скоуп, Сигнатура, КлючиЗаголовков);
Возврат ЗаголовокАвторизации;
КонецФункции
ТекущаяДата = OPI_Инструменты.ПолучитьТекущуюДату();
Функция ПолучитьКлючПодписи(Знач СекретныйКлюч, Знач Регион, Знач Сервис, Знач ТекущаяДата)
КлючДанных = OPI_Криптография.HMACSHA256("AWS4" + СекретныйКлюч, Формат(ТекущаяДата, "ДФ=yyyyMMdd;"));
КлючРегиона = OPI_Криптография.HMACSHA256(КлючДанных, Регион);
@@ -80,4 +126,155 @@
КонецФункции
Функция СоздатьКаноническийЗапрос(Знач Запрос, Знач Соединение, Знач Метод)
ТелоЗапроса = Запрос.ПолучитьТелоКакДвоичныеДанные();
ШаблонЗапроса = "";
Для Н = 1 По 6 Цикл
ШаблонЗапроса = "%" + Строка(Н) + ?(Н = 6, "", Символы.ПС);
КонецЦикла;
Метод = вРег(Метод);
СтрокаURI = ПолучитьСтрокуURI(Запрос);
СтрокаПараметров = ПолучитьСтрокуПараметров(СтрокаURI);
СтрокаЗаголовков = ПолучитьСтрокуЗаголовков(Запрос);
СтрокаКлючей = ПолучитьСтрокуКлючейЗаголовков(Запрос);
ХэшСумма = OPI_Криптография.Хеш(ТелоЗапроса, ХешФункция.SHA256);
СтрокаХэша = ПолучитьHexСтрокуИзДвоичныхДанных(ХэшСумма);
КаноническийЗапрос = СтрШаблон(ШаблонЗапроса
, Метод
, СтрокаURI
, СтрокаПараметров
, СтрокаЗаголовков
, СтрокаКлючей
, СтрокаХэша);
Возврат КаноническийЗапрос;
КонецФункции
Функция СоздатьСкоуп(Знач Регион, Знач Сервис, Знач ТекущаяДата)
ДатаОбычная = Формат(ТекущаяДата, "ДФ=yyyyMMdd;");
Скоуп = Новый Массив;
Скоуп.Добавить(ДатаОбычная);
Скоуп.Добавить(Регион);
Скоуп.Добавить(Сервис);
Скоуп.Добавить("aws4_request");
СкоупСтрокой = СтрСоединить(Скоуп, "/");
Возврат СкоупСтрокой;
КонецФункции
Функция СоздатьСтрокуПодписи(Знач КаноническийЗапрос, Знач Скоуп, Знач ТекущаяДата)
ШаблонСтроки = "";
Алгоритм = "AWS4-HMAC-SHA256";
ДатаISO = Лев(XMLСтрока(ТекущаяДата), 19) + "Z";
Для Н = 1 По 4 Цикл
ШаблонСтроки = "%" + Строка(Н) + ?(Н = 4, "", Символы.ПС);
КонецЦикла;
СтрокаПодписи = СтрШаблон(ШаблонСтроки, Алгоритм, ДатаISO, Скоуп, КаноническийЗапрос);
Возврат СтрокаПодписи;
КонецФункции
Функция ПолучитьСтрокуURI(Знач Запрос)
URI = Запрос.АдресРесурса;
URI = ?(СтрНачинаетсяС(URI, "/"), URI, "/" + URI);
НачалоПараметров = СтрНайти(URI, "?");
URI = Лев(URI, НачалоПараметров - 1);
Возврат URI;
КонецФункции
Функция ПолучитьСтрокуПараметров(Знач URI)
НачалоПараметров = СтрНайти(URI, "?");
Если НачалоПараметров = 0 Тогда
СтрокаПараметров = Символы.ПС;
Иначе
ДлинаURI = СтрДлина(URI);
СтрокаПараметров = Прав(URI, ДлинаURI - НачалоПараметров);
КонецЕсли;
МассивПараметров = СтрРазделить(СтрокаПараметров, "&");
СписокПараметров = Новый СписокЗначений();
СписокПараметров.ЗагрузитьЗначения(МассивПараметров);
СписокПараметров.СортироватьПоЗначению();
СтрокаПараметров = СтрСоединить(СписокПараметров.ВыгрузитьЗначения(), "&");
Возврат СтрокаПараметров;
КонецФункции
Функция ПолучитьСтрокуЗаголовков(Знач Запрос)
СписокЗаголовков = Новый СписокЗначений;
Заголовки = Запрос.Заголовки;
Для Каждого Заголовок Из Заголовки Цикл
СтрокаЗаголовка = нРег(Заголовок.Ключ + ":" + Заголовок.Значение);
СписокЗаголовков.Добавить(СтрокаЗаголовка);
КонецЦикла;
СписокЗаголовков.СортироватьПоЗначению();
СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), Символы.ПС);
Возврат СтрокаЗаголовков;
КонецФункции
Функция ПолучитьСтрокуКлючейЗаголовков(Знач Запрос)
СписокЗаголовков = Новый СписокЗначений;
Заголовки = Запрос.Заголовки;
Для Каждого Заголовок Из Заголовки Цикл
СтрокаЗаголовка = нРег(Заголовок.Ключ);
СписокЗаголовков.Добавить(СтрокаЗаголовка);
КонецЦикла;
СписокЗаголовков.СортироватьПоЗначению();
СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), ";");
Возврат СтрокаЗаголовков;
КонецФункции
Функция СформироватьЗаголовокАвторизации(Знач AccessKey, Знач Скоуп, Знач Сигнатура, Знач КлючиЗаголовков)
ШаблонЗаголовка = "Authorization: AWS4-HMAC-SHA256 "
+ "Credential=%1/%2, "
+ "SignedHeaders=%3, "
+ "Signature=%4";
ЗаголовокАвторизации = СтрШаблон(ШаблонЗаголовка, AccessKey, Скоуп, КлючиЗаголовков, Сигнатура);
Возврат ЗаголовокАвторизации;
КонецФункции
#КонецОбласти
@@ -2002,9 +2002,9 @@
КонецФункции
Функция ПолучитьОбщийМодуль(Знач Имя)
Модуль = Вычислить(Имя);
Возврат Модуль;
КонецФункции
@@ -564,6 +564,25 @@
КонецФункции
Функция НайтиОтсутствующиеПоляКоллекции(Знач Коллекция, Знач Поля) Экспорт
МассивОтсутствующихПолей = Новый Массив;
Для Каждого ЭлементКоллекции Из Коллекция Цикл
ТекущийКлюч = ЭлементКоллекции.Ключ;
Существует = ПолеКоллекцииСуществет(ТекущийКлюч, Коллекция);
Если Не Существует Тогда
МассивОтсутствующихПолей.Добавить(ТекущийКлюч);
КонецЕсли;
КонецЦикла;
Возврат МассивОтсутствующихПолей;
КонецФункции
Функция ОчиститьКоллекциюРекурсивно(Знач Коллекция) Экспорт
ТипЗначения = ТипЗнч(Коллекция);
+203 -6
View File
@@ -45,10 +45,15 @@
#Область ОбщиеМетоды
Функция ПолучитьСтруктуруАвторизации(Знач AccessKey, Знач SecretKey, Знач Region, Знач URL, Знач Service = "s3") Экспорт
КлючПодписи = ПолучитьКлючПодписи(SecretKey, Region, Service);
Функция ПолучитьСтруктуруАвторизации(Знач AccessKey, Знач SecretKey, Знач Region, Знач Service = "s3") Экспорт
СтруктураАвторизации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("AccessKey", AccessKey, "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("SecretKey", SecretKey, "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("Region" , Region , "Строка", СтруктураАвторизации);
OPI_Инструменты.ДобавитьПоле("Service" , Service , "Строка", СтруктураАвторизации);
Возврат СтруктураАвторизации;
КонецФункции
@@ -66,9 +71,50 @@
#Область СлужебныеПроцедурыИФункции
Функция ПолучитьКлючПодписи(Знач СекретныйКлюч, Знач Регион, Знач Сервис)
Функция СоздатьЗаголовокАвторизации(Знач СтруктураДанных, Знач Запрос, Знач Соединение, Знач Метод)
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СтруктураДанных);
Если ТипЗнч(СтруктураДанных) = Тип("Массив") Тогда
ВызватьИсключение "Ошибка получения авторизационных данных из структуры";
КонецЕсли;
МассивНеобходимыхПолей = Новый Массив;
МассивНеобходимыхПолей.Добавить("AccessKey");
МассивНеобходимыхПолей.Добавить("SecretKey");
МассивНеобходимыхПолей.Добавить("Region");
МассивНеобходимыхПолей.Добавить("Service");
ОтсутствующиеПоля = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(СтруктураДанных, МассивНеобходимыхПолей);
Если ОтсутствующиеПоля.Количество() > 0 Тогда
ВызватьИсключение "Отсутствуют необходимые данные авторизации: " + СтрСоединить(ОтсутствующиеПоля, ", ");
КонецЕсли;
AccessKey = СтруктураДанных["AccessKey"];
SecretKey = СтруктураДанных["SecretKey"];
Region = СтруктураДанных["Region"];
Service = СтруктураДанных["Service"];
ТекущаяДата = OPI_Инструменты.ПолучитьТекущуюДату();
КлючПодписи = ПолучитьКлючПодписи(SecretKey, Region, Service, ТекущаяДата);
КаноническийЗапрос = СоздатьКаноническийЗапрос(Запрос, Соединение, Метод);
Скоуп = СоздатьСкоуп(Region, Service, ТекущаяДата);
СтрокаДляПодписи = СоздатьСтрокуПодписи(КаноническийЗапрос, Скоуп, ТекущаяДата);
Сигнатура = OPI_Криптография.HMACSHA256(КлючПодписи, СтрокаДляПодписи);
Сигнатура = ПолучитьHexСтрокуИзДвоичныхДанных(Сигнатура);
КлючиЗаголовков = ПолучитьСтрокуКлючейЗаголовков(Запрос);
ЗаголовокАвторизации = СформироватьЗаголовокАвторизации(AccessKey, Скоуп, Сигнатура, КлючиЗаголовков);
Возврат ЗаголовокАвторизации;
КонецФункции
ТекущаяДата = OPI_Инструменты.ПолучитьТекущуюДату();
Функция ПолучитьКлючПодписи(Знач СекретныйКлюч, Знач Регион, Знач Сервис, Знач ТекущаяДата)
КлючДанных = OPI_Криптография.HMACSHA256("AWS4" + СекретныйКлюч, Формат(ТекущаяДата, "ДФ=yyyyMMdd;"));
КлючРегиона = OPI_Криптография.HMACSHA256(КлючДанных, Регион);
@@ -80,4 +126,155 @@
КонецФункции
Функция СоздатьКаноническийЗапрос(Знач Запрос, Знач Соединение, Знач Метод)
ТелоЗапроса = Запрос.ПолучитьТелоКакДвоичныеДанные();
ШаблонЗапроса = "";
Для Н = 1 По 6 Цикл
ШаблонЗапроса = "%" + Строка(Н) + ?(Н = 6, "", Символы.ПС);
КонецЦикла;
Метод = вРег(Метод);
СтрокаURI = ПолучитьСтрокуURI(Запрос);
СтрокаПараметров = ПолучитьСтрокуПараметров(СтрокаURI);
СтрокаЗаголовков = ПолучитьСтрокуЗаголовков(Запрос);
СтрокаКлючей = ПолучитьСтрокуКлючейЗаголовков(Запрос);
ХэшСумма = OPI_Криптография.Хеш(ТелоЗапроса, ХешФункция.SHA256);
СтрокаХэша = ПолучитьHexСтрокуИзДвоичныхДанных(ХэшСумма);
КаноническийЗапрос = СтрШаблон(ШаблонЗапроса
, Метод
, СтрокаURI
, СтрокаПараметров
, СтрокаЗаголовков
, СтрокаКлючей
, СтрокаХэша);
Возврат КаноническийЗапрос;
КонецФункции
Функция СоздатьСкоуп(Знач Регион, Знач Сервис, Знач ТекущаяДата)
ДатаОбычная = Формат(ТекущаяДата, "ДФ=yyyyMMdd;");
Скоуп = Новый Массив;
Скоуп.Добавить(ДатаОбычная);
Скоуп.Добавить(Регион);
Скоуп.Добавить(Сервис);
Скоуп.Добавить("aws4_request");
СкоупСтрокой = СтрСоединить(Скоуп, "/");
Возврат СкоупСтрокой;
КонецФункции
Функция СоздатьСтрокуПодписи(Знач КаноническийЗапрос, Знач Скоуп, Знач ТекущаяДата)
ШаблонСтроки = "";
Алгоритм = "AWS4-HMAC-SHA256";
ДатаISO = Лев(XMLСтрока(ТекущаяДата), 19) + "Z";
Для Н = 1 По 4 Цикл
ШаблонСтроки = "%" + Строка(Н) + ?(Н = 4, "", Символы.ПС);
КонецЦикла;
СтрокаПодписи = СтрШаблон(ШаблонСтроки, Алгоритм, ДатаISO, Скоуп, КаноническийЗапрос);
Возврат СтрокаПодписи;
КонецФункции
Функция ПолучитьСтрокуURI(Знач Запрос)
URI = Запрос.АдресРесурса;
URI = ?(СтрНачинаетсяС(URI, "/"), URI, "/" + URI);
НачалоПараметров = СтрНайти(URI, "?");
URI = Лев(URI, НачалоПараметров - 1);
Возврат URI;
КонецФункции
Функция ПолучитьСтрокуПараметров(Знач URI)
НачалоПараметров = СтрНайти(URI, "?");
Если НачалоПараметров = 0 Тогда
СтрокаПараметров = Символы.ПС;
Иначе
ДлинаURI = СтрДлина(URI);
СтрокаПараметров = Прав(URI, ДлинаURI - НачалоПараметров);
КонецЕсли;
МассивПараметров = СтрРазделить(СтрокаПараметров, "&");
СписокПараметров = Новый СписокЗначений();
СписокПараметров.ЗагрузитьЗначения(МассивПараметров);
СписокПараметров.СортироватьПоЗначению();
СтрокаПараметров = СтрСоединить(СписокПараметров.ВыгрузитьЗначения(), "&");
Возврат СтрокаПараметров;
КонецФункции
Функция ПолучитьСтрокуЗаголовков(Знач Запрос)
СписокЗаголовков = Новый СписокЗначений;
Заголовки = Запрос.Заголовки;
Для Каждого Заголовок Из Заголовки Цикл
СтрокаЗаголовка = нРег(Заголовок.Ключ + ":" + Заголовок.Значение);
СписокЗаголовков.Добавить(СтрокаЗаголовка);
КонецЦикла;
СписокЗаголовков.СортироватьПоЗначению();
СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), Символы.ПС);
Возврат СтрокаЗаголовков;
КонецФункции
Функция ПолучитьСтрокуКлючейЗаголовков(Знач Запрос)
СписокЗаголовков = Новый СписокЗначений;
Заголовки = Запрос.Заголовки;
Для Каждого Заголовок Из Заголовки Цикл
СтрокаЗаголовка = нРег(Заголовок.Ключ);
СписокЗаголовков.Добавить(СтрокаЗаголовка);
КонецЦикла;
СписокЗаголовков.СортироватьПоЗначению();
СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), ";");
Возврат СтрокаЗаголовков;
КонецФункции
Функция СформироватьЗаголовокАвторизации(Знач AccessKey, Знач Скоуп, Знач Сигнатура, Знач КлючиЗаголовков)
ШаблонЗаголовка = "Authorization: AWS4-HMAC-SHA256 "
+ "Credential=%1/%2, "
+ "SignedHeaders=%3, "
+ "Signature=%4";
ЗаголовокАвторизации = СтрШаблон(ШаблонЗаголовка, AccessKey, Скоуп, КлючиЗаголовков, Сигнатура);
Возврат ЗаголовокАвторизации;
КонецФункции
#КонецОбласти
@@ -564,6 +564,25 @@
КонецФункции
Функция НайтиОтсутствующиеПоляКоллекции(Знач Коллекция, Знач Поля) Экспорт
МассивОтсутствующихПолей = Новый Массив;
Для Каждого ЭлементКоллекции Из Коллекция Цикл
ТекущийКлюч = ЭлементКоллекции.Ключ;
Существует = ПолеКоллекцииСуществет(ТекущийКлюч, Коллекция);
Если Не Существует Тогда
МассивОтсутствующихПолей.Добавить(ТекущийКлюч);
КонецЕсли;
КонецЦикла;
Возврат МассивОтсутствующихПолей;
КонецФункции
Функция ОчиститьКоллекциюРекурсивно(Знач Коллекция) Экспорт
ТипЗначения = ТипЗнч(Коллекция);