diff --git a/.bsl-language-server.json b/.bsl-language-server.json index fe68c15..ec8dece 100644 --- a/.bsl-language-server.json +++ b/.bsl-language-server.json @@ -7,8 +7,9 @@ "diagnostics": { "LatinAndCyrillicSymbolInWord": false, "parameters": { + "PublicMethodsDescription": false, "Typo": { - "userWordsToIgnore": "Автосохранение, Автосохранения, автосохранения, Бьютифицировать, Бьютифицированный, Асинх, Сериализовать, сериализовать, СериализоватьПараметрыАвторизацииИзЗначения, Апи, КлючАпи" + "userWordsToIgnore": "Автосохранение, Автосохранения, автосохранения, Бьютифицировать, Бьютифицированный, Асинх, Сериализовать, сериализовать, СериализоватьПараметрыАвторизацииИзЗначения, Апи, КлючАпи, Автозаголовки, Автозаголовков, автозаголовки, автозаголовков" } } } diff --git a/CHANGELOG.md b/CHANGELOG.md index c904524..f5997b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see ## [Unreleased] +## [1.3.25] - 2026-08-07 + + + ### Added - Automatic request headers (issue #22): `Content-Type` by body mode @@ -39,6 +43,11 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see `Authorization: Bearer …` prefix (issue #12). Generic **Token** kept for a custom prefix (UI label: «Токен (свой префикс)»). Postman `bearer` import/export maps to `BearerToken`. +- Authorization type **JWT Bearer** (`JwtBearer`, issue #13): HS256/HS512 via + platform `ХешированиеДанных` + HMAC (RFC 2104), fields `algorithm` / `secret` / + `claims` (JSON) / `ttlSeconds` (`iat`/`exp` when TTL > 0). Auth schema and crypto + live in the data processor object module (shared by main and collection forms). + Postman `jwt` import/export maps for HS*. ## [1.3.24] - 2026-08-04 @@ -228,6 +237,10 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see ## [Unreleased] +## [1.3.25] - 2026-08-07 + + + ### Добавлено - Автоматические заголовки запроса (issue #22): `Content-Type` по типу тела @@ -244,6 +257,11 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see префикс `Authorization: Bearer …` (issue #12). Generic **Token** сохранён для своего префикса (в UI: «Токен (свой префикс)»). Импорт/экспорт Postman `bearer` соответствует `BearerToken`. +- Тип авторизации **JWT Bearer** (`JwtBearer`, issue #13): HS256/HS512 через + `ХешированиеДанных` платформы + HMAC (RFC 2104), поля `algorithm` / `secret` / + `claims` (JSON) / `ttlSeconds` (`iat`/`exp` при TTL > 0). Схема авторизации и + крипто вынесены в модуль объекта обработки (общие для основной формы и + коллекции). Импорт/экспорт Postman `jwt` для HS*. ## [1.3.24] - 2026-08-04 @@ -429,7 +447,8 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see - Разные исправления стабильности. -[Unreleased]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_24...HEAD +[Unreleased]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_25...HEAD +[1.3.25]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_24...v_1_3_25 [1.3.24]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_23...v_1_3_24 [1.3.23]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_22...v_1_3_23 [1.3.22]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_21...v_1_3_22 diff --git a/README.md b/README.md index 3177969..3a99bdd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://github.com/LunatikDG/GetManHTTP/blob/main/LICENSE.txt) [![1C Version](https://img.shields.io/badge/1С-8.3.26%2B-orange)](#) -[![Release](https://img.shields.io/badge/release-1.3.24-red)](https://github.com/LunatikDG/GetManHTTP/releases) +[![Release](https://img.shields.io/badge/release-1.3.25-red)](https://github.com/LunatikDG/GetManHTTP/releases) [![BSL Lint](https://github.com/LunatikDG/GetManHTTP/actions/workflows/bsl-lint.yml/badge.svg)](https://github.com/LunatikDG/GetManHTTP/actions/workflows/bsl-lint.yml)

@@ -57,8 +57,8 @@ indicator, response headers and formatted body. ![Response panel](docs/images/response-panel.png) -**Authorization** — type selector (Basic / Token / Bearer Token / API Key) with fields that adapt to -the chosen type. +**Authorization** — type selector (Basic / Token / Bearer Token / API Key / JWT Bearer) with fields that adapt to +the selected scheme. JWT Bearer signs HS256/HS512 locally (no crypto provider required). ![Authorization fields](docs/images/auth-fields.png) @@ -222,8 +222,8 @@ GetManHTTP — это HTTP-клиент, оформленный как **вне ![Панель ответа](docs/images/response-panel.png) -**Авторизация** — выбор типа (Basic / Token / Bearer Token / API Key) с полями, которые меняются в -зависимости от выбранного типа. +**Авторизация** — выбор типа (Basic / Token / Bearer Token / API Key / JWT Bearer) с полями, которые меняются в +зависимости от схемы. JWT Bearer подписывает HS256/HS512 локально (криптопровайдер не нужен). ![Поля авторизации](docs/images/auth-fields.png) diff --git a/docs/collection-format.md b/docs/collection-format.md index 79961b1..03cfecf 100644 --- a/docs/collection-format.md +++ b/docs/collection-format.md @@ -105,6 +105,7 @@ Portable authorization object (collection, folder, or request). | `Token` | collection, folder, request | `tokenPrefix`, `token` | Sent as `Authorization: {tokenPrefix} {token}`. Default prefix when empty at apply time: `Token`. `token` is secret. | | `BearerToken` | collection, folder, request | `token` | Sent as `Authorization: Bearer {token}` (fixed prefix, RFC 6750). `token` is secret. | | `ApiKey` | collection, folder, request | `key`, `value`, `addTo` | `addTo`: `Header` (default) or `Query`. Default `key` name: `X-API-Key`. `value` is secret. | +| `JwtBearer` | collection, folder, request | `algorithm`, `secret`, `claims`, `ttlSeconds` | Builds JWT (HS256/HS512) and sends `Authorization: Bearer {jwt}`. `algorithm` default `HS256`; `claims` is a JSON object string; `ttlSeconds` > 0 sets `iat`/`exp` (Unix). `secret` is secret. | | `InheritFromOwner` | folder, request | _(none)_ | Walk up folder → collection auth. **Not** valid as collection root auth (importers coerce unsupported types to the context default). | --- @@ -377,6 +378,7 @@ v2.1: файлы Postman определяются отдельно и преоб | `Token` | коллекция, папка, запрос | `tokenPrefix`, `token` | Заголовок `Authorization: {tokenPrefix} {token}`. Префикс по умолчанию при применении: `Token`. `token` — секрет. | | `BearerToken` | коллекция, папка, запрос | `token` | Заголовок `Authorization: Bearer {token}` (фиксированный префикс, RFC 6750). `token` — секрет. | | `ApiKey` | коллекция, папка, запрос | `key`, `value`, `addTo` | `addTo`: `Header` (по умолчанию) или `Query`. Имя ключа по умолчанию: `X-API-Key`. `value` — секрет. | +| `JwtBearer` | коллекция, папка, запрос | `algorithm`, `secret`, `claims`, `ttlSeconds` | Собирает JWT (HS256/HS512) и шлёт `Authorization: Bearer {jwt}`. `algorithm` по умолчанию `HS256`; `claims` — JSON-объект строкой; `ttlSeconds` > 0 задаёт `iat`/`exp` (Unix). `secret` — секрет. | | `InheritFromOwner` | папка, запрос | _(нет)_ | Наследование папка → коллекция. На корне коллекции не используется. | --- diff --git a/docs/images/auth-fields.png b/docs/images/auth-fields.png index f45efa7..874da65 100644 Binary files a/docs/images/auth-fields.png and b/docs/images/auth-fields.png differ diff --git a/docs/images/main-form.png b/docs/images/main-form.png index a8c146d..23a22b2 100644 Binary files a/docs/images/main-form.png and b/docs/images/main-form.png differ diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" index 7e53b53..37b36ce 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" @@ -2,7 +2,7 @@ <key>ru</key> - <value>GetManHTTP (HTTP-клиент): v1.3.24</value> + <value>GetManHTTP (HTTP-клиент): v1.3.25</value> ГруппаЛево @@ -2094,6 +2094,15 @@ ApiKey + + + ru + JWT Bearer + + + JwtBearer + + true diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" index 0e1fb21..0cb7789 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" @@ -83,7 +83,8 @@

Настройка HTTP-запроса

  • базовая — логин и пароль в HTTP-соединение;
  • по токену (свой префикс) — заголовок Authorization (префикс по умолчанию Token);
  • Bearer Token — заголовок Authorization: Bearer … (фиксированный префикс);
  • -
  • API Key — имя и значение ключа с выбором «добавить в заголовок» или «в Query-параметр».
  • +
  • API Key — имя и значение ключа с выбором «добавить в заголовок» или «в Query-параметр»;
  • +
  • JWT Bearer — генерация JWT (алгоритмы HS256/HS512), секрет, Claims (JSON), TTL для iat/exp; заголовок Authorization: Bearer ….
  • Тело запроса — варианты: отсутствует, JSON, XML, form-data (текстовые и файловые поля, несколько файлов в одном multipart; лимит размера тела 50 МБ), двоичные данные (один файл целиком).
  • @@ -124,7 +125,7 @@

    Обратная связь

    Ошибки и предложения: репозиторий на GitHub, почта main@lunatikdg.ru, Telegram @LunatikDG.

    -

    Версия обработки: 1.3.24

    +

    Версия обработки: 1.3.25

    diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" index d0ab3d9..4d075d6 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" @@ -89,7 +89,7 @@ &НаКлиенте Процедура ТипАвторизацииПриИзменении(Элемент) - ПерестроитьПараметрыАвторизацииПоСхемеОбщий(ПараметрыАвторизации, ТипАвторизации, Ложь); + ПерестроитьПараметрыАвторизацииПоСхемеНаСервереБезСохраненияЗначений(); ОтобразитьПоляАвторизацииПоСхеме(); КонецПроцедуры @@ -1915,7 +1915,7 @@ Процедура ОтобразитьПоляАвторизацииПоСхеме() Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизации(ПараметрыАвторизации); + ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); КоличествоПолейСхемы = Схема.Поля.Количество(); @@ -2003,7 +2003,7 @@ ОписаниеПоля = Схема.Поля[Индекс - 1]; ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоЧислаБезГруппировки(Индекс); - УстановитьЗначениеПараметраАвторизации( + УстановитьЗначениеПараметраАвторизацииНаКлиенте( ПараметрыАвторизации, ОписаниеПоля.Ключ, ЭтотОбъект[ИмяРеквизита], @@ -2016,7 +2016,7 @@ &НаКлиенте Процедура ПерестроитьПараметрыАвторизацииПоСхеме() - ПерестроитьПараметрыАвторизацииПоСхемеОбщий(ПараметрыАвторизации, ТипАвторизации); + ПерестроитьПараметрыАвторизацииПоСхемеНаСервере(); КонецПроцедуры @@ -2028,6 +2028,14 @@ КонецПроцедуры +&НаСервере +Процедура ПерестроитьПараметрыАвторизацииПоСхемеНаСервереБезСохраненияЗначений() + + ПерестроитьПараметрыАвторизацииПоСхемеОбщий(ПараметрыАвторизации, ТипАвторизации, Ложь); + ЗаполнитьЗначенияПолейАвторизацииНаСервере(); + +КонецПроцедуры + &НаСервере Процедура ЗаполнитьЗначенияПолейАвторизацииНаСервере() @@ -2131,10 +2139,11 @@ ЭффективнаяАвторизация = ПолучитьЭффективнуюАвторизациюТекущегоЭлементаНаСервере(); URI.ТипАвторизации = ЭффективнаяАвторизация.ТипАвторизации; - ПрименитьПравилаАвторизацииКСтруктуреURI( - URI, + ДанныеBasic = ЛогинПарольАвторизацииНаСервере( ЭффективнаяАвторизация.ТипАвторизации, ЭффективнаяАвторизация.ЗначенияПараметров); + URI.Логин = ДанныеBasic.Логин; + URI.Пароль = ДанныеBasic.Пароль; КонецПроцедуры @@ -2148,7 +2157,7 @@ ЧастиПути = ОтделитьQueryИЯкорьОтПути(URI.ПутьНаСервере); СтрокаПараметров = ПараметрыВСтроку(); ЭффективнаяАвторизация = ПолучитьЭффективнуюАвторизациюТекущегоЭлементаНаСервере(); - СтрокаАвторизации = СтрокаПараметровАвторизацииЗапроса( + СтрокаАвторизации = СтрокаПараметровАвторизацииЗапросаНаСервере( ЭффективнаяАвторизация.ТипАвторизации, ЭффективнаяАвторизация.ЗначенияПараметров); @@ -2164,6 +2173,24 @@ КонецПроцедуры +&НаСервере +Функция ЛогинПарольАвторизацииНаСервере(Знач ТипАвторизации, Знач ЗначенияПараметров) + + ДанныеBasic = Новый Структура; + ДанныеBasic.Вставить("Логин", ""); + ДанныеBasic.Вставить("Пароль", ""); + ПрименитьПравилаАвторизацииКСтруктуреURI(ДанныеBasic, ТипАвторизации, ЗначенияПараметров); + Возврат ДанныеBasic; + +КонецФункции + +&НаСервере +Функция СтрокаПараметровАвторизацииЗапросаНаСервере(Знач ТипАвторизации, Знач ЗначенияПараметров) + + Возврат СтрокаПараметровАвторизацииЗапроса(ТипАвторизации, ЗначенияПараметров); + +КонецФункции + // Отделяет query (?...) и якорь (#...) от пути (часть после хоста в URI). // Вызывается с клиента и с сервера. // @@ -3290,7 +3317,7 @@ &НаКлиентеНаСервереБезКонтекста Функция ВерсияОбработки() - Возврат "1.3.24"; + Возврат "1.3.25"; КонецФункции @@ -6653,12 +6680,7 @@ &НаСервере Функция ЭтоПоддерживаемыйТипАвторизацииКоллекции(Знач ТипАвторизации) - Возврат ТипАвторизации = "BasicAuth" - Или ТипАвторизации = ИдентификаторТипаАвторизацииТокен() - Или ТипАвторизации = ИдентификаторТипаАвторизацииBearerToken() - Или ТипАвторизации = ИдентификаторТипаАвторизацииApiKey() - Или ТипАвторизации = ИдентификаторТипаАвторизацииБезАвторизации() - Или ТипАвторизации = ИдентификаторТипаАвторизацииНаследоватьОтВладельца(); + Возврат ОбъектОбработкиАвторизации().ЭтоПоддерживаемыйТипАвторизации(ТипАвторизации); КонецФункции @@ -6744,7 +6766,39 @@ Возврат Результат; КонецЕсли; - // jwt, oauth1, oauth2 и прочее - не поддерживаются. + Если ТипPostman = "jwt" Тогда + Результат.ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer(); + ПараметрыJwt = ЗначениеСвойстваJSONКоллекции(ОписаниеАвторизации, "jwt", Новый Массив); + АлгоритмJwt = ЗначениеПараметраPostmanAuth(ПараметрыJwt, "algorithm"); + АлгоритмJwt = ОбъектОбработкиАвторизации().НормализованныйАлгоритмJwt(АлгоритмJwt); + УстановитьЗначениеПараметраАвторизации( + Результат.ПараметрыАвторизации, + КлючПоляАвторизацииJwtАлгоритм(), + АлгоритмJwt, + Ложь); + УстановитьЗначениеПараметраАвторизации( + Результат.ПараметрыАвторизации, + КлючПоляАвторизацииJwtСекрет(), + ЗначениеПараметраPostmanAuth(ПараметрыJwt, "secret"), + Истина); + PayloadJwt = ЗначениеПараметраPostmanAuth(ПараметрыJwt, "payload"); + Если ПустаяСтрока(PayloadJwt) Тогда + PayloadJwt = "{}"; + КонецЕсли; + УстановитьЗначениеПараметраАвторизации( + Результат.ПараметрыАвторизации, + КлючПоляАвторизацииJwtClaims(), + PayloadJwt, + Ложь); + УстановитьЗначениеПараметраАвторизации( + Результат.ПараметрыАвторизации, + КлючПоляАвторизацииJwtTTL(), + "0", + Ложь); + Возврат Результат; + КонецЕсли; + + // oauth1, oauth2 и прочее - не поддерживаются. Возврат Результат; КонецФункции @@ -6827,6 +6881,26 @@ Возврат Результат; КонецЕсли; + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() Тогда + АлгоритмJwt = ЗначениеПараметраАвторизацииИзТаблицы( + ПараметрыАвторизации, + КлючПоляАвторизацииJwtАлгоритм()); + СекретJwt = ЗначениеПараметраАвторизацииИзТаблицы( + ПараметрыАвторизации, + КлючПоляАвторизацииJwtСекрет()); + ClaimsJwt = ЗначениеПараметраАвторизацииИзТаблицы( + ПараметрыАвторизации, + КлючПоляАвторизацииJwtClaims()); + Результат = Новый Структура; + Результат.Вставить(КлючType, "jwt"); + МассивПараметров = Новый Массив; + МассивПараметров.Добавить(ПараметрPostmanAuth("algorithm", АлгоритмJwt, ТипСтрока)); + МассивПараметров.Добавить(ПараметрPostmanAuth("secret", СекретJwt, ТипСтрока)); + МассивПараметров.Добавить(ПараметрPostmanAuth("payload", ClaimsJwt, ТипСтрока)); + Результат.Вставить("jwt", МассивПараметров); + Возврат Результат; + КонецЕсли; + Возврат Неопределено; КонецФункции @@ -7245,12 +7319,15 @@ #Область СхемаАвторизации -// Реестр схем авторизации. Чтобы добавить новый тип: -// 1) Добавьте значение в список выбора ТипАвторизации на форме. -// 2) Опишите поля и правила в ОписаниеСхемыАвторизации. -// Виды правил: ConnectionBasic, Header, Query, HeaderOrQuery -// (для Query: структура с полями Вид="Query", Имя, Шаблон; -// для HeaderOrQuery: КлючИмени, КлючЗначения, КлючРежима - Header|Query). +// Идентификаторы типов и ключей полей дублируют ObjectModule (нужны на клиенте). +// Схема полей/правил, применение и JWT - только в модуле объекта. + +&НаСервере +Функция ОбъектОбработкиАвторизации() + + Возврат РеквизитФормыВЗначение("Объект"); + +КонецФункции &НаКлиентеНаСервереБезКонтекста Функция МаксимумПолейАвторизацииНаФорме() @@ -7287,6 +7364,13 @@ КонецФункции +&НаКлиентеНаСервереБезКонтекста +Функция ИдентификаторТипаАвторизацииJwtBearer() + + Возврат "JwtBearer"; + +КонецФункции + &НаКлиентеНаСервереБезКонтекста Функция ИдентификаторТипаАвторизацииБезАвторизации() @@ -7316,13 +7400,6 @@ КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция ПрефиксBearerАвторизации() - - Возврат "Bearer"; - -КонецФункции - &НаКлиентеНаСервереБезКонтекста Функция КлючПоляАвторизацииПрефиксТокена() @@ -7359,267 +7436,123 @@ КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция РежимДобавленияApiKeyВЗаголовок() +Функция КлючПоляАвторизацииJwtАлгоритм() - Возврат "Header"; + Возврат "algorithm"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция РежимДобавленияApiKeyВQuery() +Функция КлючПоляАвторизацииJwtСекрет() - Возврат "Query"; + Возврат "secret"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция ИмяЗаголовкаApiKeyПоУмолчанию() +Функция КлючПоляАвторизацииJwtClaims() - Возврат "X-API-Key"; + Возврат "claims"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) +Функция КлючПоляАвторизацииJwtTTL() - Схема = Новый Структура; - Схема.Вставить("Поля", Новый Массив); - Схема.Вставить("Правила", Новый Массив); - - Если ТипАвторизации = "BasicAuth" Тогда - - ПолеЛогина = НовоеПолеСхемыАвторизации("login", "Логин", Ложь, Ложь, ""); - ПолеПароля = НовоеПолеСхемыАвторизации("password", "Пароль", Истина, Ложь, ""); - ПравилоBasic = НовоеПравилоАвторизацииБазовогоСоединения("login", "password"); - - Схема.Поля.Добавить(ПолеЛогина); - Схема.Поля.Добавить(ПолеПароля); - Схема.Правила.Добавить(ПравилоBasic); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииТокен() Тогда - - ПолеПрефикса = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииПрефиксТокена(), - "Префикс токена", - Ложь, - Ложь, - ПрефиксТокенаАвторизацииПоУмолчанию()); - ПолеТокена = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииТокен(), - "Токен", - Истина, - Ложь, - ""); - ШаблонЗаголовка = "{" + КлючПоляАвторизацииПрефиксТокена() + "} {" - + КлючПоляАвторизацииТокен() + "}"; - ПравилоЗаголовка = НовоеПравилоАвторизацииЗаголовка("Authorization", ШаблонЗаголовка); - - Схема.Поля.Добавить(ПолеПрефикса); - Схема.Поля.Добавить(ПолеТокена); - Схема.Правила.Добавить(ПравилоЗаголовка); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииBearerToken() Тогда - - ПолеТокена = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииТокен(), - "Токен", - Истина, - Ложь, - ""); - ШаблонЗаголовка = ПрефиксBearerАвторизации() + " {" + КлючПоляАвторизацииТокен() + "}"; - ПравилоЗаголовка = НовоеПравилоАвторизацииЗаголовка("Authorization", ШаблонЗаголовка); - - Схема.Поля.Добавить(ПолеТокена); - Схема.Правила.Добавить(ПравилоЗаголовка); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииApiKey() Тогда - - ПолеИмени = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииApiKeyИмя(), - "Имя ключа", - Ложь, - Ложь, - ИмяЗаголовкаApiKeyПоУмолчанию()); - ПолеЗначения = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииApiKeyЗначение(), - "Значение", - Истина, - Ложь, - ""); - ПолеРежима = НовоеПолеСхемыАвторизации( - КлючПоляАвторизацииApiKeyДобавитьВ(), - "Добавить в", - Ложь, - Ложь, - РежимДобавленияApiKeyВЗаголовок(), - ВариантыВыбораРежимаApiKey()); - ПравилоApiKey = НовоеПравилоАвторизацииHeaderOrQuery( - КлючПоляАвторизацииApiKeyИмя(), - КлючПоляАвторизацииApiKeyЗначение(), - КлючПоляАвторизацииApiKeyДобавитьВ()); - - Схема.Поля.Добавить(ПолеИмени); - Схема.Поля.Добавить(ПолеЗначения); - Схема.Поля.Добавить(ПолеРежима); - Схема.Правила.Добавить(ПравилоApiKey); - - Иначе - Возврат Схема; - КонецЕсли; - - Возврат Схема; + Возврат "ttlSeconds"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция ВариантыВыбораРежимаApiKey() +Функция РежимДобавленияApiKeyВЗаголовок() - Результат = Новый Массив; - РежимЗаголовок = РежимДобавленияApiKeyВЗаголовок(); - РежимQuery = РежимДобавленияApiKeyВQuery(); - Результат.Добавить(НовыйВариантВыбораПоляАвторизации(РежимЗаголовок, "Заголовок")); - Результат.Добавить(НовыйВариантВыбораПоляАвторизации(РежимQuery, "Query-параметр")); - Возврат Результат; + Возврат "Header"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция НовыйВариантВыбораПоляАвторизации(Знач Значение, Знач Представление) +Функция РежимДобавленияApiKeyВQuery() - Вариант = Новый Структура; - Вариант.Вставить("Значение", Значение); - Вариант.Вставить("Представление", Представление); - Возврат Вариант; + Возврат "Query"; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция НовоеПолеСхемыАвторизации( - Знач Ключ, - Знач Заголовок, - Знач Секретный, - Знач Многострочный, - Знач ЗначениеПоУмолчанию, - Знач ВариантыВыбора = Неопределено) - - Поле = Новый Структура; - Поле.Вставить("Ключ", Ключ); - Поле.Вставить("Заголовок", Заголовок); - Поле.Вставить("Секретный", Секретный); - Поле.Вставить("Многострочный", Многострочный); - Поле.Вставить("ЗначениеПоУмолчанию", ЗначениеПоУмолчанию); - Если ВариантыВыбора = Неопределено Тогда - Поле.Вставить("ВариантыВыбора", Новый Массив); - Иначе - Поле.Вставить("ВариантыВыбора", ВариантыВыбора); - КонецЕсли; +Функция ИмяЗаголовкаApiKeyПоУмолчанию() - Возврат Поле; + Возврат "X-API-Key"; КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция НовоеПравилоАвторизацииБазовогоСоединения(Знач КлючЛогина, Знач КлючПароля) - - Правило = Новый Структура; - Правило.Вставить("Вид", "ConnectionBasic"); - Правило.Вставить("КлючЛогина", КлючЛогина); - Правило.Вставить("КлючПароля", КлючПароля); +&НаСервере +Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) - Возврат Правило; + Возврат ОбъектОбработкиАвторизации().ОписаниеСхемыАвторизации(ТипАвторизации); КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция НовоеПравилоАвторизацииЗаголовка(Знач ИмяЗаголовка, Знач ШаблонЗначения) - - Правило = Новый Структура; - Правило.Вставить("Вид", "Header"); - Правило.Вставить("Имя", ИмяЗаголовка); - Правило.Вставить("Шаблон", ШаблонЗначения); +&НаСервере +Процедура ПерестроитьПараметрыАвторизацииПоСхемеОбщий( + ТаблицаПараметров, + Знач ТипАвторизации, + Знач СохранятьЗначения = Истина) - Возврат Правило; + ОбъектОбработкиАвторизации().ПерестроитьПараметрыАвторизацииПоСхеме( + ТаблицаПараметров, + ТипАвторизации, + СохранятьЗначения); -КонецФункции +КонецПроцедуры -&НаКлиентеНаСервереБезКонтекста -Функция НовоеПравилоАвторизацииHeaderOrQuery(Знач КлючИмени, Знач КлючЗначения, Знач КлючРежима) - - Правило = Новый Структура; - Правило.Вставить("Вид", "HeaderOrQuery"); - Правило.Вставить("КлючИмени", КлючИмени); - Правило.Вставить("КлючЗначения", КлючЗначения); - Правило.Вставить("КлючРежима", КлючРежима); +&НаСервере +Функция СоответствиеЗначенийПараметровАвторизации(Знач ТаблицаПараметров) - Возврат Правило; + Возврат ОбъектОбработкиАвторизации().СоответствиеЗначенийПараметровАвторизации(ТаблицаПараметров); КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция НормализованныйРежимДобавленияApiKey(Знач Режим) - - РежимНорм = ВРег(СокрЛП(Строка(Режим))); - Если РежимНорм = ВРег(РежимДобавленияApiKeyВQuery()) - Или РежимНорм = "QUERY" Тогда - Возврат РежимДобавленияApiKeyВQuery(); - КонецЕсли; +&НаСервере +Процедура УстановитьЗначениеПараметраАвторизации(ТаблицаПараметров, Знач Ключ, Знач Значение, Знач Секретный) - Возврат РежимДобавленияApiKeyВЗаголовок(); + ОбъектОбработкиАвторизации().УстановитьЗначениеПараметраАвторизации( + ТаблицаПараметров, + Ключ, + Значение, + Секретный); -КонецФункции +КонецПроцедуры -&НаКлиентеНаСервереБезКонтекста -Процедура ПерестроитьПараметрыАвторизацииПоСхемеОбщий( - ТаблицаПараметров, - Знач ТипАвторизации, - Знач СохранятьЗначения = Истина) - - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - СтарыеЗначения = Новый Соответствие; - - Если СохранятьЗначения Тогда - Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл - СтарыеЗначения.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); - КонецЦикла; - КонецЕсли; - - ТаблицаПараметров.Очистить(); +&НаСервере +Процедура ПрименитьПравилаАвторизацииКСтруктуреURI(URI, Знач ТипАвторизации, Знач ЗначенияПараметров) - Для Каждого ОписаниеПоля Из Схема.Поля Цикл - - ЗначениеПоля = Неопределено; - Если СохранятьЗначения Тогда - ЗначениеПоля = СтарыеЗначения.Получить(ОписаниеПоля.Ключ); - КонецЕсли; - Если ЗначениеПоля = Неопределено Тогда - ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; - КонецЕсли; - - УстановитьЗначениеПараметраАвторизации( - ТаблицаПараметров, - ОписаниеПоля.Ключ, - ЗначениеПоля, - ОписаниеПоля.Секретный); - - КонецЦикла; + ОбъектОбработкиАвторизации().ПрименитьПравилаАвторизацииКСтруктуреURI( + URI, + ТипАвторизации, + ЗначенияПараметров); КонецПроцедуры -&НаКлиентеНаСервереБезКонтекста -Функция СоответствиеЗначенийПараметровАвторизации(Знач ТаблицаПараметров) +&НаСервере +Процедура ПрименитьПравилаАвторизацииКЗаголовкам(Заголовки, Знач ТипАвторизации, Знач ЗначенияПараметров) - Результат = Новый Соответствие; + ОбъектОбработкиАвторизации().ПрименитьПравилаАвторизацииКЗаголовкам( + Заголовки, + ТипАвторизации, + ЗначенияПараметров); - Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл - Результат.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); - КонецЦикла; +КонецПроцедуры + +&НаСервере +Функция СтрокаПараметровАвторизацииЗапроса(Знач ТипАвторизации, Знач ЗначенияПараметров) - Возврат Результат; + Возврат ОбъектОбработкиАвторизации().СтрокаПараметровАвторизацииЗапроса( + ТипАвторизации, + ЗначенияПараметров); КонецФункции -&НаКлиентеНаСервереБезКонтекста -Процедура УстановитьЗначениеПараметраАвторизации(ТаблицаПараметров, Знач Ключ, Знач Значение, Знач Секретный) +&НаКлиенте +Процедура УстановитьЗначениеПараметраАвторизацииНаКлиенте(ТаблицаПараметров, Знач Ключ, Знач Значение, Знач Секретный) Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл @@ -7638,134 +7571,26 @@ КонецПроцедуры -&НаКлиентеНаСервереБезКонтекста -Функция ЗначениеПараметраАвторизацииИзСоответствия(Знач ЗначенияПараметров, Знач Ключ, Знач ЗначениеПоУмолчанию = "") - - Значение = ЗначенияПараметров.Получить(Ключ); - Если Значение = Неопределено Тогда - Возврат ЗначениеПоУмолчанию; - КонецЕсли; +&НаСервере +Функция НормализованныйРежимДобавленияApiKey(Знач Режим) - Возврат Значение; + Возврат ОбъектОбработкиАвторизации().НормализованныйРежимДобавленияApiKey(Режим); КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция ПодставитьПараметрыВШаблонАвторизации(Знач Шаблон, Знач ЗначенияПараметров) +&НаКлиенте +Функция СоответствиеЗначенийПараметровАвторизацииНаКлиенте(Знач ТаблицаПараметров) - Результат = Строка(Шаблон); + Результат = Новый Соответствие; - Для Каждого КлючИЗначение Из ЗначенияПараметров Цикл - Результат = СтрЗаменить(Результат, "{" + КлючИЗначение.Ключ + "}", Строка(КлючИЗначение.Значение)); + Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл + Результат.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); КонецЦикла; Возврат Результат; КонецФункции -&НаКлиентеНаСервереБезКонтекста -Процедура ПрименитьПравилаАвторизацииКСтруктуреURI(URI, Знач ТипАвторизации, Знач ЗначенияПараметров) - - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - - Для Каждого Правило Из Схема.Правила Цикл - - Если Правило.Вид = "ConnectionBasic" Тогда - URI.Логин = ЗначениеПараметраАвторизацииИзСоответствия(ЗначенияПараметров, Правило.КлючЛогина); - URI.Пароль = ЗначениеПараметраАвторизацииИзСоответствия(ЗначенияПараметров, Правило.КлючПароля); - КонецЕсли; - - КонецЦикла; - -КонецПроцедуры - -&НаКлиентеНаСервереБезКонтекста -Процедура ПрименитьПравилаАвторизацииКЗаголовкам(Заголовки, Знач ТипАвторизации, Знач ЗначенияПараметров) - - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - - Для Каждого Правило Из Схема.Правила Цикл - - Если Правило.Вид = "Header" Тогда - - ЗначениеЗаголовка = ПодставитьПараметрыВШаблонАвторизации(Правило.Шаблон, ЗначенияПараметров); - Заголовки.Вставить(Правило.Имя, ЗначениеЗаголовка); - - КонецЕсли; - - Если Правило.Вид = "HeaderOrQuery" Тогда - - РежимИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючРежима); - Режим = НормализованныйРежимДобавленияApiKey(РежимИзПараметров); - Если Режим = РежимДобавленияApiKeyВЗаголовок() Тогда - - ИмяИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючИмени); - ИмяЗаголовка = СокрЛП(Строка(ИмяИзПараметров)); - Если Не ПустаяСтрока(ИмяЗаголовка) Тогда - ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючЗначения); - ЗначениеЗаголовка = Строка(ЗначениеИзПараметров); - Заголовки.Вставить(ИмяЗаголовка, ЗначениеЗаголовка); - КонецЕсли; - - КонецЕсли; - - КонецЕсли; - - КонецЦикла; - -КонецПроцедуры - -&НаКлиентеНаСервереБезКонтекста -Функция СтрокаПараметровАвторизацииЗапроса(Знач ТипАвторизации, Знач ЗначенияПараметров) - - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - Части = Новый Массив; - - Для Каждого Правило Из Схема.Правила Цикл - - Если Правило.Вид = "Query" Тогда - - ЗначениеПараметра = ПодставитьПараметрыВШаблонАвторизации(Правило.Шаблон, ЗначенияПараметров); - Части.Добавить(Правило.Имя + "=" + ЗначениеПараметра); - - КонецЕсли; - - Если Правило.Вид = "HeaderOrQuery" Тогда - - РежимИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючРежима); - Режим = НормализованныйРежимДобавленияApiKey(РежимИзПараметров); - Если Режим = РежимДобавленияApiKeyВQuery() Тогда - - ИмяИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючИмени); - ИмяПараметра = СокрЛП(Строка(ИмяИзПараметров)); - Если Не ПустаяСтрока(ИмяПараметра) Тогда - ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - Правило.КлючЗначения); - ЗначениеПараметра = Строка(ЗначениеИзПараметров); - Части.Добавить(ИмяПараметра + "=" + ЗначениеПараметра); - КонецЕсли; - - КонецЕсли; - - КонецЕсли; - - КонецЦикла; - - Возврат СтрСоединить(Части, "&"); - -КонецФункции - #КонецОбласти #КонецОбласти diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" index 6a51e4b..a2bcd75 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" @@ -257,6 +257,15 @@ ApiKey + + + ru + JWT Bearer + + + JwtBearer + + true diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" index 6e963b9..f8bfdb9 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" @@ -198,17 +198,31 @@ КонецПроцедуры +&НаСервере +Функция ОбъектОбработкиАвторизации() + + Возврат РеквизитФормыВЗначение("Объект"); + +КонецФункции + +&НаСервере +Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) + + Возврат ОбъектОбработкиАвторизации().ОписаниеСхемыАвторизации(ТипАвторизации); + +КонецФункции + &НаКлиенте Процедура ОтобразитьПоляАвторизацииПоСхеме() - Схема = ОписаниеСхемыАвторизацииКоллекции(ТипАвторизации); - ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииКоллекции(ПараметрыАвторизации); - МаксимумПолей = МаксимумПолейАвторизацииНаФормеКоллекции(); + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); + МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); КоличествоПолейСхемы = Схема.Поля.Количество(); Для Индекс = 1 По МаксимумПолей Цикл - ИндексСтрокой = ФорматЦелогоБезГруппировкиКоллекции(Индекс); + ИндексСтрокой = ФорматЦелогоБезГруппировки(Индекс); ИмяЭлемента = "ПолеАвторизации" + ИндексСтрокой; ИмяРеквизита = "ЗначениеАвторизации" + ИндексСтрокой; ЭлементПоля = Элементы[ИмяЭлемента]; @@ -234,14 +248,14 @@ ЭлементПоля.РежимПароля = ОписаниеПоля.Секретный; ЭлементПоля.МногострочныйРежим = ОписаниеПоля.Многострочный; ЭлементПоля.Высота = ?(ОписаниеПоля.Многострочный, 5, 1); - НастроитьСписокВыбораПоляАвторизацииКоллекции(ЭлементПоля, ОписаниеПоля); + НастроитьСписокВыбораПоляАвторизации(ЭлементПоля, ОписаниеПоля); КонецЦикла; КонецПроцедуры &НаКлиенте -Процедура НастроитьСписокВыбораПоляАвторизацииКоллекции(ЭлементПоля, Знач ОписаниеПоля) +Процедура НастроитьСписокВыбораПоляАвторизации(ЭлементПоля, Знач ОписаниеПоля) ЭлементПоля.СписокВыбора.Очистить(); @@ -277,14 +291,14 @@ &НаКлиенте Процедура СинхронизироватьПараметрыАвторизацииИзПолейФормы() - Схема = ОписаниеСхемыАвторизацииКоллекции(ТипАвторизации); - КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолейАвторизацииНаФормеКоллекции()); + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолейАвторизацииНаФорме()); Для Индекс = 1 По КоличествоПолейСхемы Цикл ОписаниеПоля = Схема.Поля[Индекс - 1]; - ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоБезГруппировкиКоллекции(Индекс); - УстановитьЗначениеПараметраАвторизацииКоллекции( + ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоБезГруппировки(Индекс); + УстановитьЗначениеПараметраАвторизацииНаКлиенте( ПараметрыАвторизации, ОписаниеПоля.Ключ, ЭтотОбъект[ИмяРеквизита], @@ -304,34 +318,10 @@ &НаСервере Процедура ПерестроитьПараметрыАвторизацииПоСхемеНаСервере(Знач СохранятьЗначения = Истина) - Схема = ОписаниеСхемыАвторизацииКоллекции(ТипАвторизации); - СтарыеЗначения = Новый Соответствие; - - Если СохранятьЗначения Тогда - Для Каждого СтрокаПараметра Из ПараметрыАвторизации Цикл - СтарыеЗначения.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); - КонецЦикла; - КонецЕсли; - - ПараметрыАвторизации.Очистить(); - - Для Каждого ОписаниеПоля Из Схема.Поля Цикл - - ЗначениеПоля = Неопределено; - Если СохранятьЗначения Тогда - ЗначениеПоля = СтарыеЗначения.Получить(ОписаниеПоля.Ключ); - КонецЕсли; - Если ЗначениеПоля = Неопределено Тогда - ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; - КонецЕсли; - - УстановитьЗначениеПараметраАвторизацииКоллекции( - ПараметрыАвторизации, - ОписаниеПоля.Ключ, - ЗначениеПоля, - ОписаниеПоля.Секретный); - - КонецЦикла; + ОбъектОбработкиАвторизации().ПерестроитьПараметрыАвторизацииПоСхеме( + ПараметрыАвторизации, + ТипАвторизации, + СохранятьЗначения); КонецПроцедуры @@ -355,160 +345,21 @@ КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция ОписаниеСхемыАвторизацииКоллекции(Знач ТипАвторизации) - - Схема = Новый Структура; - Схема.Вставить("Поля", Новый Массив); - - Если ТипАвторизации = "BasicAuth" Тогда - - ПолеЛогина = НовоеПолеСхемыАвторизацииКоллекции("login", "Логин", Ложь, Ложь, ""); - ПолеПароля = НовоеПолеСхемыАвторизацииКоллекции("password", "Пароль", Истина, Ложь, ""); - Схема.Поля.Добавить(ПолеЛогина); - Схема.Поля.Добавить(ПолеПароля); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииТокенКоллекции() Тогда - - ПолеПрефикса = НовоеПолеСхемыАвторизацииКоллекции( - "tokenPrefix", - "Префикс токена", - Ложь, - Ложь, - ИдентификаторТипаАвторизацииТокенКоллекции()); - ПолеТокена = НовоеПолеСхемыАвторизацииКоллекции( - "token", - "Токен", - Истина, - Ложь, - ""); - Схема.Поля.Добавить(ПолеПрефикса); - Схема.Поля.Добавить(ПолеТокена); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииТокенНосителяКоллекции() Тогда - - ПолеТокена = НовоеПолеСхемыАвторизацииКоллекции( - "token", - "Токен", - Истина, - Ложь, - ""); - Схема.Поля.Добавить(ПолеТокена); - - ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииКлючАпиКоллекции() Тогда - - ПолеИмени = НовоеПолеСхемыАвторизацииКоллекции( - "key", - "Имя ключа", - Ложь, - Ложь, - "X-API-Key"); - ПолеЗначения = НовоеПолеСхемыАвторизацииКоллекции( - "value", - "Значение", - Истина, - Ложь, - ""); - ПолеРежима = НовоеПолеСхемыАвторизацииКоллекции( - "addTo", - "Добавить в", - Ложь, - Ложь, - "Header", - ВариантыВыбораРежимаКлючАпиКоллекции()); - Схема.Поля.Добавить(ПолеИмени); - Схема.Поля.Добавить(ПолеЗначения); - Схема.Поля.Добавить(ПолеРежима); - - Иначе - Возврат Схема; - КонецЕсли; - - Возврат Схема; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция ВариантыВыбораРежимаКлючАпиКоллекции() - - Результат = Новый Массив; - Результат.Добавить(НовыйВариантВыбораПоляАвторизацииКоллекции("Header", "Заголовок")); - Результат.Добавить(НовыйВариантВыбораПоляАвторизацииКоллекции("Query", "Query-параметр")); - Возврат Результат; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция НовыйВариантВыбораПоляАвторизацииКоллекции(Знач Значение, Знач Представление) - - Вариант = Новый Структура; - Вариант.Вставить("Значение", Значение); - Вариант.Вставить("Представление", Представление); - Возврат Вариант; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция НовоеПолеСхемыАвторизацииКоллекции( - Знач Ключ, - Знач Заголовок, - Знач Секретный, - Знач Многострочный, - Знач ЗначениеПоУмолчанию, - Знач ВариантыВыбора = Неопределено) - - Поле = Новый Структура; - Поле.Вставить("Ключ", Ключ); - Поле.Вставить("Заголовок", Заголовок); - Поле.Вставить("Секретный", Секретный); - Поле.Вставить("Многострочный", Многострочный); - Поле.Вставить("ЗначениеПоУмолчанию", ЗначениеПоУмолчанию); - Если ВариантыВыбора = Неопределено Тогда - Поле.Вставить("ВариантыВыбора", Новый Массив); - Иначе - Поле.Вставить("ВариантыВыбора", ВариантыВыбора); - КонецЕсли; - - Возврат Поле; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция МаксимумПолейАвторизацииНаФормеКоллекции() +Функция МаксимумПолейАвторизацииНаФорме() Возврат 6; КонецФункции &НаКлиентеНаСервереБезКонтекста -Функция ФорматЦелогоБезГруппировкиКоллекции(Знач Число) +Функция ФорматЦелогоБезГруппировки(Знач Число) Возврат Формат(Число, "ЧГ=0"); КонецФункции -&НаКлиентеНаСервереБезКонтекста -Функция ИдентификаторТипаАвторизацииТокенКоллекции() - - Возврат "Token"; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция ИдентификаторТипаАвторизацииТокенНосителяКоллекции() - - Возврат "BearerToken"; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция ИдентификаторТипаАвторизацииКлючАпиКоллекции() - - Возврат "ApiKey"; - -КонецФункции - -&НаКлиентеНаСервереБезКонтекста -Функция СоответствиеЗначенийПараметровАвторизацииКоллекции(Знач ТаблицаПараметров) +&НаКлиенте +Функция СоответствиеЗначенийПараметровАвторизацииНаКлиенте(Знач ТаблицаПараметров) Результат = Новый Соответствие; @@ -520,8 +371,8 @@ КонецФункции -&НаКлиентеНаСервереБезКонтекста -Процедура УстановитьЗначениеПараметраАвторизацииКоллекции(ТаблицаПараметров, Знач Ключ, Знач Значение, Знач Секретный) +&НаКлиенте +Процедура УстановитьЗначениеПараметраАвторизацииНаКлиенте(ТаблицаПараметров, Знач Ключ, Знач Значение, Знач Секретный) Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл diff --git a/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl b/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl index 4a4aa80..6520f2a 100644 --- a/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl +++ b/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl @@ -1,4 +1,6 @@ // strict-types (annotation without at-sign to avoid UsingServiceTag) +// Имена с URI/JSON/JWT намеренно смешивают латиницу и кириллицу. +// BSLLS:LatinAndCyrillicSymbolInWord-off #Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда @@ -20,6 +22,957 @@ КонецФункции +#Область Авторизация + +// Максимум слотов полей авторизации на формах обработки. +// +// Возвращаемое значение: +// Число - максимальное количество полей авторизации на форме. +// +Функция МаксимумПолейАвторизацииНаФорме() Экспорт + + Возврат 6; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииТокен() Экспорт + + Возврат "Token"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииBearerToken() Экспорт + + Возврат "BearerToken"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииApiKey() Экспорт + + Возврат "ApiKey"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииJwtBearer() Экспорт + + Возврат "JwtBearer"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииБезАвторизации() Экспорт + + Возврат "NoAuth"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииНаследоватьОтВладельца() Экспорт + + Возврат "InheritFromOwner"; + +КонецФункции + +Функция ИдентификаторТипаАвторизацииBasicAuth() Экспорт + + Возврат "BasicAuth"; + +КонецФункции + +Функция ЭтоТипАвторизацииНаследоватьОтВладельца(Знач ТипАвторизации) Экспорт + + Возврат ТипАвторизации = ИдентификаторТипаАвторизацииНаследоватьОтВладельца() + Или ПустаяСтрока(ТипАвторизации); + +КонецФункции + +Функция ЭтоПоддерживаемыйТипАвторизации(Знач ТипАвторизации) Экспорт + + Возврат ТипАвторизации = ИдентификаторТипаАвторизацииBasicAuth() + Или ТипАвторизации = ИдентификаторТипаАвторизацииТокен() + Или ТипАвторизации = ИдентификаторТипаАвторизацииBearerToken() + Или ТипАвторизации = ИдентификаторТипаАвторизацииApiKey() + Или ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() + Или ТипАвторизации = ИдентификаторТипаАвторизацииБезАвторизации() + Или ТипАвторизации = ИдентификаторТипаАвторизацииНаследоватьОтВладельца(); + +КонецФункции + +Функция ПрефиксТокенаАвторизацииПоУмолчанию() Экспорт + + Возврат ИдентификаторТипаАвторизацииТокен(); + +КонецФункции + +Функция ПрефиксBearerАвторизации() Экспорт + + Возврат "Bearer"; + +КонецФункции + +Функция ИмяЗаголовкаAuthorization() Экспорт + + Возврат "Authorization"; + +КонецФункции + +Функция КлючПоляАвторизацииПрефиксТокена() Экспорт + + Возврат "tokenPrefix"; + +КонецФункции + +Функция КлючПоляАвторизацииТокен() Экспорт + + Возврат "token"; + +КонецФункции + +Функция КлючПоляАвторизацииApiKeyИмя() Экспорт + + Возврат "key"; + +КонецФункции + +Функция КлючПоляАвторизацииApiKeyЗначение() Экспорт + + Возврат "value"; + +КонецФункции + +Функция КлючПоляАвторизацииApiKeyДобавитьВ() Экспорт + + Возврат "addTo"; + +КонецФункции + +Функция КлючПоляАвторизацииJwtАлгоритм() Экспорт + + Возврат "algorithm"; + +КонецФункции + +Функция КлючПоляАвторизацииJwtСекрет() Экспорт + + Возврат "secret"; + +КонецФункции + +Функция КлючПоляАвторизацииJwtClaims() Экспорт + + Возврат "claims"; + +КонецФункции + +Функция КлючПоляАвторизацииJwtTTL() Экспорт + + Возврат "ttlSeconds"; + +КонецФункции + +Функция РежимДобавленияApiKeyВЗаголовок() Экспорт + + Возврат "Header"; + +КонецФункции + +Функция РежимДобавленияApiKeyВQuery() Экспорт + + Возврат "Query"; + +КонецФункции + +Функция ИмяЗаголовкаApiKeyПоУмолчанию() Экспорт + + Возврат "X-API-Key"; + +КонецФункции + +Функция АлгоритмJwtHS256() Экспорт + + Возврат "HS256"; + +КонецФункции + +Функция АлгоритмJwtHS512() Экспорт + + Возврат "HS512"; + +КонецФункции + +Функция ВидПравилаАвторизацииComputedHeader() Экспорт + + Возврат "ComputedHeader"; + +КонецФункции + +Функция ОбработчикComputedHeaderJwtBearer() Экспорт + + Возврат ИдентификаторТипаАвторизацииJwtBearer(); + +КонецФункции + +// Возвращает схему полей и правил для типа авторизации. +// +// Параметры: +// ТипАвторизации - Строка - идентификатор типа (BasicAuth, Token, BearerToken, ApiKey, JwtBearer, …). +// +// Возвращаемое значение: +// Структура - Поля (Массив), Правила (Массив). +// +Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) Экспорт + + Схема = Новый Структура; + Схема.Вставить("Поля", Новый Массив); + Схема.Вставить("Правила", Новый Массив); + + Если ТипАвторизации = ИдентификаторТипаАвторизацииBasicAuth() Тогда + + ПолеЛогина = НовоеПолеСхемыАвторизации("login", "Логин", Ложь, Ложь, ""); + ПолеПароля = НовоеПолеСхемыАвторизации("password", "Пароль", Истина, Ложь, ""); + ПравилоBasic = НовоеПравилоАвторизацииБазовогоСоединения("login", "password"); + + Схема.Поля.Добавить(ПолеЛогина); + Схема.Поля.Добавить(ПолеПароля); + Схема.Правила.Добавить(ПравилоBasic); + + ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииТокен() Тогда + + ПолеПрефикса = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииПрефиксТокена(), + "Префикс токена", + Ложь, + Ложь, + ПрефиксТокенаАвторизацииПоУмолчанию()); + ПолеТокена = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииТокен(), + "Токен", + Истина, + Ложь, + ""); + ШаблонЗаголовка = "{" + КлючПоляАвторизацииПрефиксТокена() + "} {" + + КлючПоляАвторизацииТокен() + "}"; + ПравилоЗаголовка = НовоеПравилоАвторизацииЗаголовка(ИмяЗаголовкаAuthorization(), ШаблонЗаголовка); + + Схема.Поля.Добавить(ПолеПрефикса); + Схема.Поля.Добавить(ПолеТокена); + Схема.Правила.Добавить(ПравилоЗаголовка); + + ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииBearerToken() Тогда + + ПолеТокена = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииТокен(), + "Токен", + Истина, + Ложь, + ""); + ШаблонЗаголовка = ПрефиксBearerАвторизации() + " {" + КлючПоляАвторизацииТокен() + "}"; + ПравилоЗаголовка = НовоеПравилоАвторизацииЗаголовка(ИмяЗаголовкаAuthorization(), ШаблонЗаголовка); + + Схема.Поля.Добавить(ПолеТокена); + Схема.Правила.Добавить(ПравилоЗаголовка); + + ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииApiKey() Тогда + + ПолеИмени = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииApiKeyИмя(), + "Имя ключа", + Ложь, + Ложь, + ИмяЗаголовкаApiKeyПоУмолчанию()); + ПолеЗначения = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииApiKeyЗначение(), + "Значение", + Истина, + Ложь, + ""); + ПолеРежима = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииApiKeyДобавитьВ(), + "Добавить в", + Ложь, + Ложь, + РежимДобавленияApiKeyВЗаголовок(), + ВариантыВыбораРежимаApiKey()); + ПравилоApiKey = НовоеПравилоАвторизацииHeaderOrQuery( + КлючПоляАвторизацииApiKeyИмя(), + КлючПоляАвторизацииApiKeyЗначение(), + КлючПоляАвторизацииApiKeyДобавитьВ()); + + Схема.Поля.Добавить(ПолеИмени); + Схема.Поля.Добавить(ПолеЗначения); + Схема.Поля.Добавить(ПолеРежима); + Схема.Правила.Добавить(ПравилоApiKey); + + ИначеЕсли ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() Тогда + + ПолеАлгоритма = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииJwtАлгоритм(), + "Алгоритм", + Ложь, + Ложь, + АлгоритмJwtHS256(), + ВариантыВыбораАлгоритмаJwt()); + ПолеСекрета = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииJwtСекрет(), + "Секрет", + Истина, + Ложь, + ""); + ПолеClaims = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииJwtClaims(), + "Claims (JSON)", + Ложь, + Истина, + "{}"); + ПолеTTL = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииJwtTTL(), + "TTL (сек)", + Ложь, + Ложь, + "3600"); + ПравилоJwt = НовоеПравилоАвторизацииComputedHeader( + ИмяЗаголовкаAuthorization(), + ОбработчикComputedHeaderJwtBearer()); + + Схема.Поля.Добавить(ПолеАлгоритма); + Схема.Поля.Добавить(ПолеСекрета); + Схема.Поля.Добавить(ПолеClaims); + Схема.Поля.Добавить(ПолеTTL); + Схема.Правила.Добавить(ПравилоJwt); + + Иначе + Возврат Схема; + КонецЕсли; + + Возврат Схема; + +КонецФункции + +Процедура ПерестроитьПараметрыАвторизацииПоСхеме( + ТаблицаПараметров, + Знач ТипАвторизации, + Знач СохранятьЗначения = Истина) Экспорт + + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + СтарыеЗначения = Новый Соответствие; + + Если СохранятьЗначения Тогда + Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл + СтарыеЗначения.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); + КонецЦикла; + КонецЕсли; + + ТаблицаПараметров.Очистить(); + + Для Каждого ОписаниеПоля Из Схема.Поля Цикл + + ЗначениеПоля = Неопределено; + Если СохранятьЗначения Тогда + ЗначениеПоля = СтарыеЗначения.Получить(ОписаниеПоля.Ключ); + КонецЕсли; + Если ЗначениеПоля = Неопределено Тогда + ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; + КонецЕсли; + + УстановитьЗначениеПараметраАвторизации( + ТаблицаПараметров, + ОписаниеПоля.Ключ, + ЗначениеПоля, + ОписаниеПоля.Секретный); + + КонецЦикла; + +КонецПроцедуры + +Функция СоответствиеЗначенийПараметровАвторизации(Знач ТаблицаПараметров) Экспорт + + Результат = Новый Соответствие; + + Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл + Результат.Вставить(СтрокаПараметра.Ключ, СтрокаПараметра.Значение); + КонецЦикла; + + Возврат Результат; + +КонецФункции + +Процедура УстановитьЗначениеПараметраАвторизации( + ТаблицаПараметров, + Знач Ключ, + Знач Значение, + Знач Секретный) Экспорт + + Для Каждого СтрокаПараметра Из ТаблицаПараметров Цикл + + Если СтрокаПараметра.Ключ = Ключ Тогда + СтрокаПараметра.Значение = Значение; + СтрокаПараметра.Секретный = Секретный; + Возврат; + КонецЕсли; + + КонецЦикла; + + НоваяСтрока = ТаблицаПараметров.Добавить(); + НоваяСтрока.Ключ = Ключ; + НоваяСтрока.Значение = Значение; + НоваяСтрока.Секретный = Секретный; + +КонецПроцедуры + +Функция ЗначениеПараметраАвторизацииИзСоответствия( + Знач ЗначенияПараметров, + Знач Ключ, + Знач ЗначениеПоУмолчанию = "") Экспорт + + Значение = ЗначенияПараметров.Получить(Ключ); + Если Значение = Неопределено Тогда + Возврат ЗначениеПоУмолчанию; + КонецЕсли; + + Возврат Значение; + +КонецФункции + +Процедура ПрименитьПравилаАвторизацииКСтруктуреURI( + URI, + Знач ТипАвторизации, + Знач ЗначенияПараметров) Экспорт + + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + + Для Каждого Правило Из Схема.Правила Цикл + + Если Правило.Вид = "ConnectionBasic" Тогда + URI.Логин = ЗначениеПараметраАвторизацииИзСоответствия(ЗначенияПараметров, Правило.КлючЛогина); + URI.Пароль = ЗначениеПараметраАвторизацииИзСоответствия(ЗначенияПараметров, Правило.КлючПароля); + КонецЕсли; + + КонецЦикла; + +КонецПроцедуры + +Процедура ПрименитьПравилаАвторизацииКЗаголовкам( + Заголовки, + Знач ТипАвторизации, + Знач ЗначенияПараметров) Экспорт + + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + + Для Каждого Правило Из Схема.Правила Цикл + + Если Правило.Вид = "Header" Тогда + + ЗначениеЗаголовка = ПодставитьПараметрыВШаблонАвторизации(Правило.Шаблон, ЗначенияПараметров); + Заголовки.Вставить(Правило.Имя, ЗначениеЗаголовка); + + КонецЕсли; + + Если Правило.Вид = "HeaderOrQuery" Тогда + ПрименитьПравилоHeaderOrQueryКЗаголовкам(Заголовки, Правило, ЗначенияПараметров); + КонецЕсли; + + Если Правило.Вид = ВидПравилаАвторизацииComputedHeader() Тогда + + ЗначениеЗаголовка = ВычислитьЗначениеComputedHeaderАвторизации( + Правило.Обработчик, + ЗначенияПараметров); + Если ЗначениеЗаголовка <> Неопределено Тогда + Заголовки.Вставить(Правило.Имя, ЗначениеЗаголовка); + КонецЕсли; + + КонецЕсли; + + КонецЦикла; + +КонецПроцедуры + +Функция СтрокаПараметровАвторизацииЗапроса(Знач ТипАвторизации, Знач ЗначенияПараметров) Экспорт + + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + Части = Новый Массив; + + Для Каждого Правило Из Схема.Правила Цикл + + Если Правило.Вид = "Query" Тогда + + ЗначениеПараметра = ПодставитьПараметрыВШаблонАвторизации(Правило.Шаблон, ЗначенияПараметров); + Части.Добавить(Правило.Имя + "=" + ЗначениеПараметра); + + КонецЕсли; + + Если Правило.Вид = "HeaderOrQuery" Тогда + ДобавитьПараметрHeaderOrQueryВМассив(Части, Правило, ЗначенияПараметров); + КонецЕсли; + + КонецЦикла; + + Возврат СтрСоединить(Части, "&"); + +КонецФункции + +// Собирает JWT (header.payload.signature) по параметрам схемы JwtBearer. +// +// Параметры: +// ЗначенияПараметров - Соответствие - значения полей схемы (algorithm, secret, claims, ttlSeconds). +// +// Возвращаемое значение: +// Строка - компактный JWT или пустая строка при отсутствии данных для подписи. +// +Функция СобратьJwtBearerТокен(Знач ЗначенияПараметров) Экспорт + + КлючАлгоритма = КлючПоляАвторизацииJwtАлгоритм(); + АлгоритмПоУмолчанию = АлгоритмJwtHS256(); + АлгоритмИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючАлгоритма, + АлгоритмПоУмолчанию); + Алгоритм = НормализованныйАлгоритмJwt(АлгоритмИзПараметров); + + КлючСекрета = КлючПоляАвторизацииJwtСекрет(); + СекретИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючСекрета, + ""); + Секрет = Строка(СекретИзПараметров); + + КлючClaims = КлючПоляАвторизацииJwtClaims(); + ClaimsИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючClaims, + "{}"); + ClaimsТекст = Строка(ClaimsИзПараметров); + + КлючTTL = КлючПоляАвторизацииJwtTTL(); + TTLИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючTTL, + "0"); + TTLСтрока = Строка(TTLИзПараметров); + + Payload = ПрочитатьClaimsJwtИзJSON(ClaimsТекст); + ПрименитьTTLКClaimsJwt(Payload, TTLСтрока); + + ЗаголовокJwt = Новый Структура; + ЗаголовокJwt.Вставить("alg", Алгоритм); + ЗаголовокJwt.Вставить("typ", "JWT"); + + ЧастьЗаголовка = Base64URLИзСтрокиUTF8(ЗаписатьЗначениеВJSONСтрокуАвторизации(ЗаголовокJwt)); + ЧастьPayload = Base64URLИзСтрокиUTF8(ЗаписатьЗначениеВJSONСтрокуАвторизации(Payload)); + ПодписываемыеДанные = ЧастьЗаголовка + "." + ЧастьPayload; + + Подпись = HMACJwt(Секрет, ПодписываемыеДанные, Алгоритм); + + Возврат ПодписываемыеДанные + "." + Base64URLИзДвоичныхДанных(Подпись); + +КонецФункции + +Функция НормализованныйАлгоритмJwt(Знач Алгоритм) Экспорт + + АлгоритмНорм = ВРег(СокрЛП(Строка(Алгоритм))); + Если АлгоритмНорм = АлгоритмJwtHS512() Тогда + Возврат АлгоритмJwtHS512(); + КонецЕсли; + + Возврат АлгоритмJwtHS256(); + +КонецФункции + +Функция НормализованныйРежимДобавленияApiKey(Знач Режим) Экспорт + + РежимНорм = ВРег(СокрЛП(Строка(Режим))); + Если РежимНорм = ВРег(РежимДобавленияApiKeyВQuery()) + Или РежимНорм = "QUERY" Тогда + Возврат РежимДобавленияApiKeyВQuery(); + КонецЕсли; + + Возврат РежимДобавленияApiKeyВЗаголовок(); + +КонецФункции + +#КонецОбласти + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +#Область АвторизацияСлужебные + +Процедура ПрименитьПравилоHeaderOrQueryКЗаголовкам(Заголовки, Знач Правило, Знач ЗначенияПараметров) + + РежимИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючРежима); + Режим = НормализованныйРежимДобавленияApiKey(РежимИзПараметров); + Если Режим <> РежимДобавленияApiKeyВЗаголовок() Тогда + Возврат; + КонецЕсли; + + ИмяИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючИмени); + ИмяЗаголовка = СокрЛП(Строка(ИмяИзПараметров)); + Если ПустаяСтрока(ИмяЗаголовка) Тогда + Возврат; + КонецЕсли; + + ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючЗначения); + ЗначениеЗаголовка = Строка(ЗначениеИзПараметров); + Заголовки.Вставить(ИмяЗаголовка, ЗначениеЗаголовка); + +КонецПроцедуры + +Процедура ДобавитьПараметрHeaderOrQueryВМассив(Части, Знач Правило, Знач ЗначенияПараметров) + + РежимИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючРежима); + Режим = НормализованныйРежимДобавленияApiKey(РежимИзПараметров); + Если Режим <> РежимДобавленияApiKeyВQuery() Тогда + Возврат; + КонецЕсли; + + ИмяИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючИмени); + ИмяПараметра = СокрЛП(Строка(ИмяИзПараметров)); + Если ПустаяСтрока(ИмяПараметра) Тогда + Возврат; + КонецЕсли; + + ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + Правило.КлючЗначения); + ЗначениеПараметраСтрокой = Строка(ЗначениеИзПараметров); + Части.Добавить(ИмяПараметра + "=" + ЗначениеПараметраСтрокой); + +КонецПроцедуры + +Функция ВариантыВыбораРежимаApiKey() + + Результат = Новый Массив; + РежимЗаголовок = РежимДобавленияApiKeyВЗаголовок(); + РежимQuery = РежимДобавленияApiKeyВQuery(); + ВариантЗаголовок = НовыйВариантВыбораПоляАвторизации(РежимЗаголовок, "Заголовок"); + ВариантQuery = НовыйВариантВыбораПоляАвторизации(РежимQuery, "Query-параметр"); + Результат.Добавить(ВариантЗаголовок); + Результат.Добавить(ВариантQuery); + Возврат Результат; + +КонецФункции + +Функция ВариантыВыбораАлгоритмаJwt() + + Результат = Новый Массив; + АлгоритмHS256 = АлгоритмJwtHS256(); + АлгоритмHS512 = АлгоритмJwtHS512(); + ВариантHS256 = НовыйВариантВыбораПоляАвторизации(АлгоритмHS256, АлгоритмHS256); + ВариантHS512 = НовыйВариантВыбораПоляАвторизации(АлгоритмHS512, АлгоритмHS512); + Результат.Добавить(ВариантHS256); + Результат.Добавить(ВариантHS512); + Возврат Результат; + +КонецФункции + +Функция НовыйВариантВыбораПоляАвторизации(Знач Значение, Знач Представление) + + Вариант = Новый Структура; + Вариант.Вставить("Значение", Значение); + Вариант.Вставить("Представление", Представление); + Возврат Вариант; + +КонецФункции + +Функция НовоеПолеСхемыАвторизации( + Знач Ключ, + Знач Заголовок, + Знач Секретный, + Знач Многострочный, + Знач ЗначениеПоУмолчанию, + Знач ВариантыВыбора = Неопределено) + + Поле = Новый Структура; + Поле.Вставить("Ключ", Ключ); + Поле.Вставить("Заголовок", Заголовок); + Поле.Вставить("Секретный", Секретный); + Поле.Вставить("Многострочный", Многострочный); + Поле.Вставить("ЗначениеПоУмолчанию", ЗначениеПоУмолчанию); + Если ВариантыВыбора = Неопределено Тогда + Поле.Вставить("ВариантыВыбора", Новый Массив); + Иначе + Поле.Вставить("ВариантыВыбора", ВариантыВыбора); + КонецЕсли; + + Возврат Поле; + +КонецФункции + +Функция НовоеПравилоАвторизацииБазовогоСоединения(Знач КлючЛогина, Знач КлючПароля) + + Правило = Новый Структура; + Правило.Вставить("Вид", "ConnectionBasic"); + Правило.Вставить("КлючЛогина", КлючЛогина); + Правило.Вставить("КлючПароля", КлючПароля); + + Возврат Правило; + +КонецФункции + +Функция НовоеПравилоАвторизацииЗаголовка(Знач ИмяЗаголовка, Знач ШаблонЗначения) + + Правило = Новый Структура; + Правило.Вставить("Вид", "Header"); + Правило.Вставить("Имя", ИмяЗаголовка); + Правило.Вставить("Шаблон", ШаблонЗначения); + + Возврат Правило; + +КонецФункции + +Функция НовоеПравилоАвторизацииHeaderOrQuery(Знач КлючИмени, Знач КлючЗначения, Знач КлючРежима) + + Правило = Новый Структура; + Правило.Вставить("Вид", "HeaderOrQuery"); + Правило.Вставить("КлючИмени", КлючИмени); + Правило.Вставить("КлючЗначения", КлючЗначения); + Правило.Вставить("КлючРежима", КлючРежима); + + Возврат Правило; + +КонецФункции + +Функция НовоеПравилоАвторизацииComputedHeader(Знач ИмяЗаголовка, Знач Обработчик) + + Правило = Новый Структура; + Правило.Вставить("Вид", ВидПравилаАвторизацииComputedHeader()); + Правило.Вставить("Имя", ИмяЗаголовка); + Правило.Вставить("Обработчик", Обработчик); + + Возврат Правило; + +КонецФункции + +Функция ПодставитьПараметрыВШаблонАвторизации(Знач Шаблон, Знач ЗначенияПараметров) + + Результат = Строка(Шаблон); + + Для Каждого КлючИЗначение Из ЗначенияПараметров Цикл + Результат = СтрЗаменить(Результат, "{" + КлючИЗначение.Ключ + "}", Строка(КлючИЗначение.Значение)); + КонецЦикла; + + Возврат Результат; + +КонецФункции + +Функция ВычислитьЗначениеComputedHeaderАвторизации(Знач Обработчик, Знач ЗначенияПараметров) + + Если Обработчик = ОбработчикComputedHeaderJwtBearer() Тогда + Токен = СобратьJwtBearerТокен(ЗначенияПараметров); + Если ПустаяСтрока(Токен) Тогда + Возврат Неопределено; + КонецЕсли; + Возврат ПрефиксBearerАвторизации() + " " + Токен; + КонецЕсли; + + Возврат Неопределено; + +КонецФункции + +Функция ПрочитатьClaimsJwtИзJSON(Знач ТекстJSON) + + Результат = Новый Соответствие; + Текст = СокрЛП(Строка(ТекстJSON)); + Если ПустаяСтрока(Текст) Тогда + Возврат Результат; + КонецЕсли; + + Попытка + Чтение = Новый ЧтениеJSON; + Чтение.УстановитьСтроку(Текст); + Значение = ПрочитатьJSON(Чтение, Истина); + Чтение.Закрыть(); + Исключение + ВызватьИсключение "Некорректный JSON в Claims JWT: " + + ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); + КонецПопытки; + + Если ТипЗнч(Значение) = Тип("Соответствие") Тогда + Возврат Значение; + ИначеЕсли ТипЗнч(Значение) = Тип("Структура") Тогда + Для Каждого КлючИЗначение Из Значение Цикл + Результат.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение); + КонецЦикла; + Возврат Результат; + Иначе + ВызватьИсключение "Claims JWT должны быть JSON-объектом"; + КонецЕсли; + +КонецФункции + +Процедура ПрименитьTTLКClaimsJwt(Payload, Знач TTLСтрока) + + ОписаниеЧисла = Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(РазрядностьЦелогоTTL(), 0)); + TTLЧисло = ОписаниеЧисла.ПривестиЗначение(СокрЛП(Строка(TTLСтрока))); + + Если TTLЧисло <= 0 Тогда + Возврат; + КонецЕсли; + + Сейчас = ТекущийUnixTimestamp(); + ВремяИстечения = Сейчас + Цел(TTLЧисло); + Payload.Вставить("iat", Сейчас); + Payload.Вставить("exp", ВремяИстечения); + +КонецПроцедуры + +Функция ТекущийUnixTimestamp() + + Возврат Цел(ТекущаяУниверсальнаяДата() - Дата(1970, 1, 1, 0, 0, 0)); + +КонецФункции + +Функция ЗаписатьЗначениеВJSONСтрокуАвторизации(Знач Значение) + + Запись = Новый ЗаписьJSON; + Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет)); + ЗаписатьJSON(Запись, Значение); + Возврат Запись.Закрыть(); + +КонецФункции + +Функция Base64URLИзСтрокиUTF8(Знач СтрокаДанных) + + Возврат Base64URLИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзСтроки(СтрокаДанных, КодировкаТекста.UTF8)); + +КонецФункции + +Функция Base64URLИзДвоичныхДанных(Знач ДвоичныеДанные) + + Результат = Base64Строка(ДвоичныеДанные); + Результат = СтрЗаменить(Результат, Символы.ПС, ""); + Результат = СтрЗаменить(Результат, Символы.ВК, ""); + Результат = СтрЗаменить(Результат, "+", "-"); + Результат = СтрЗаменить(Результат, "/", "_"); + + Пока Прав(Результат, 1) = "=" Цикл + Результат = Лев(Результат, СтрДлина(Результат) - 1); + КонецЦикла; + + Возврат Результат; + +КонецФункции + +Функция HMACJwt(Знач Секрет, Знач Данные, Знач Алгоритм) + + Если Алгоритм = АлгоритмJwtHS512() Тогда + Возврат HMACПоХешФункции(Секрет, Данные, ХешФункция.SHA512, РазмерБлокаHmacSha512()); + КонецЕсли; + + Возврат HMACПоХешФункции(Секрет, Данные, ХешФункция.SHA256, РазмерБлокаHmacSha256()); + +КонецФункции + +// HMAC (RFC 2104) поверх встроенного ХешированиеДанных. +// +// Параметры: +// КлючСтрока - Строка - секретный ключ. +// ДанныеСтрока - Строка - подписываемые данные. +// ТипХеша - ХешФункция - SHA256 или SHA512. +// РазмерБлока - Число - размер блока HMAC в байтах (64 для SHA256, 128 для SHA512). +// +// Возвращаемое значение: +// ДвоичныеДанные - код аутентификации сообщения. +// +Функция HMACПоХешФункции(Знач КлючСтрока, Знач ДанныеСтрока, Знач ТипХеша, Знач РазмерБлока) + + Ключ = ПолучитьДвоичныеДанныеИзСтроки(Строка(КлючСтрока), КодировкаТекста.UTF8); + Данные = ПолучитьДвоичныеДанныеИзСтроки(Строка(ДанныеСтрока), КодировкаТекста.UTF8); + + Если Ключ.Размер() > РазмерБлока Тогда + Ключ = ХешСуммаДвоичныхДанных(Ключ, ТипХеша); + КонецЕсли; + + КлючHex = ПолучитьHexСтрокуИзДвоичныхДанных(Ключ); + Если Ключ.Размер() < РазмерБлока Тогда + КлючHex = Лев(КлючHex + ПовторитьHexБайт("00", РазмерБлока), РазмерБлока * ДлинаHexСимволовНаБайт()); + КонецЕсли; + КлючБуфер = ПолучитьБуферДвоичныхДанныхИзHexСтроки(КлючHex); + + Ipad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьHexБайт("36", РазмерБлока)); + Opad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьHexБайт("5c", РазмерБлока)); + Ipad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер); + Opad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер); + + ВнутренниеДанные = СоединитьДвоичныеДанныеИзБуферов( + Ipad, + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Данные)); + ВнутреннийХеш = ХешСуммаДвоичныхДанных(ВнутренниеДанные, ТипХеша); + ВнешниеДанные = СоединитьДвоичныеДанныеИзБуферов( + Opad, + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ВнутреннийХеш)); + + Возврат ХешСуммаДвоичныхДанных(ВнешниеДанные, ТипХеша); + +КонецФункции + +Функция ХешСуммаДвоичныхДанных(Знач ДвоичныеДанные, Знач ТипХеша) + + Хеширование = Новый ХешированиеДанных(ТипХеша); + Хеширование.Добавить(ДвоичныеДанные); + Возврат Хеширование.ХешСумма; + +КонецФункции + +Функция ПовторитьHexБайт(Знач HexБайт, Знач Количество) + + Результат = ""; + ДлинаЦели = Количество * ДлинаHexСимволовНаБайт(); + Пока СтрДлина(Результат) < ДлинаЦели Цикл + Результат = Результат + HexБайт; + КонецЦикла; + + Возврат Результат; + +КонецФункции + +Функция СоединитьДвоичныеДанныеИзБуферов(Знач Буфер1, Знач Буфер2) + + Данные1 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер1); + Данные2 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер2); + Части = Новый Массив; + Части.Добавить(Данные1); + Части.Добавить(Данные2); + Возврат СоединитьДвоичныеДанные(Части); + +КонецФункции + +Функция РазмерБлокаHmacSha256() + + Возврат 64; + +КонецФункции + +Функция РазмерБлокаHmacSha512() + + Возврат 128; + +КонецФункции + +Функция ДлинаHexСимволовНаБайт() + + Возврат 2; + +КонецФункции + +Функция РазрядностьЦелогоTTL() + + Возврат 10; + +КонецФункции + +#КонецОбласти + #КонецОбласти #КонецЕсли + +// BSLLS:LatinAndCyrillicSymbolInWord-on