© 2014 - 2024 esia.pro
Библиотека авторизации через ЕСИА (Java)
1 Общее описание
Библиотека содержит набор функций реализованных на языке программирования Java позволяющих организовать взаимодействие с сервисами Единой системы идентификации и аутентификации (ЕСИА) по протоколу OAuth 2.0. Подробную информацию о данном протоколе и принципах взаимодействия с ЕСИА можно получить в методических рекомендациях по использованию ЕСИА
2 Перечень поставляемых файлов
В состав файлов, поставляемых с библиотекой, входят следующие:
- oauth2 - директория, в которой содержатся основные файлы библиотеки;
- scope - директория моделей;
- org/OrgDetails.java - модель для представления детализованных данных организации;
- usr/PersonAddress.java - модель для представления данных по адресам пользователя;
- usr/PersonContact.java - модель для представления контактных данных пользователя;
- usr/PersonDocument.java - модель для представления данных по документам пользователя;
- usr/PersonInfo.java - модель для представления базового набора данных о пользователе (ФИО, СНИЛС, ИНН и т.п.);
- usr/PersonKid.java - модель для представления данных по детям пользователя;
- usr/PersonOrg.java - модель для представления базового набора данных по организациям пользователя;
- usr/PersonVehicle.java - модель для представления данных по транспортным средствам пользователя;
- AccessTokenRefresher.java - интерфейс сервиса обновления маркера доступа;
- AccessTokenRefresherV1.java - сервис обновления маркера доступа, использующий API V1;
- AccessTokenRequester.java - интерфейс сервиса запроса маркера доступа;
- AccessTokenRequesterV1.java - сервис запроса маркера доступа, использующий API V1;
- AccessTokenRequesterV3.java - сервис запроса маркера доступа, использующий API V3;
- AccessTokenResponse.java - внутренний класс. Ответ от ЕСИА с результатами аутентификации;
- AccessTokenVerifier.java - интерфейс сервиса проверки маркера доступа на валидность;
- AccessType.java - тип доступа к ресурсам (online, offline);
- AuthService.java - интерфейс сервиса, отвечающий за авторизацию, получение маркера доступа, его обновление и выход;
- AuthState.java - текущее состояние авторизации, содержит в себе маркер доступа, маркер обновления и информацию о времени истечения маркера доступа:
- AuthStateStorage.java - интерфейс хранилища авторизационных данных. Обычно для этих целей используется БД (Redis, PostgreSQL …).
- AuthorizedHttpClient.java - HTTP клиент с поддержкой авторизации. Является обёрткой над простым HTTP клиентом. Его основная задача добавлять заголовок авторизации с маркером доступа и обновлять маркер доступа при необходимости;
- Configuration.java - конфигурация сервисов библиотеки;
- DateProvider.java - интерфейс поставщика времени;
- EsiaAuthService.java - реализация сервиса авторизации для ЕСИА;
- EsiaDomain.java - основные домены ЕСИА;
- EsiaException.java - ошибки ЕСИА;
- EsiaTokenVerifier.java - проверка маркера доступа ЕСИА на валидность. Используемые алгоритмы ГОСТ 3410-2012-256, RSA 256;
- LoginRequest.java - информация для выполнения запроса авторизации;
- LoginUrlBuilder.java - интерфейс сервиса формирования URL для запроса авторизационного кода;
- LoginUrlBuilderV1.java - сервиса формирования URL для запроса авторизационного кода, использующий API V1;
- LoginUrlBuilderV2.java - сервиса формирования URL для запроса авторизационного кода, использующий API V2;
- Parameters.java - набор различных констант параметров для авторизации в ЕСИА;
- PersonInfoService.java - сервис получения пользовательских данных;
- RealtimeDateProvider.java - поставщик реального времени;
- StateGenerator.java - интерфейс генератора идентификаторов state;
- Utils.java - различные вспомогательные функции;
- UuidStateGenerator.java - state генератор, основанный на UUID;
- ParametrizedScope.java - разрешение на получения набора данных с поддержкой параметров;
- BaseScope.java - интерфейс разрешения на получение набора данных;
- Scope.java - разрешения на предоставляемые наборы данных;
- scope - директория моделей;
- crypto - различные классы, связанные с криптографией;
- CertWithKey.java - структура, содержащая в себе сертификат и приватный ключ;
- CryptoAlgorithm.java - используемые крипто-алгоритмы;
- CryptoService.java - интерфейс крипто-сервиса;
- CryptoServiceJwtAlgorithm.java - внутренний класс. Алгоритм проверки подписи JWT, использующий крипто-сервис для проверки подписи;
- FileCertLoader.java - загрузка сертификатов и приватных ключей из файлов;
- HashAlgorithm.java - поддерживаемые алгоритмы хеширования;
- KeyStoreCertLoader.java - загрузка сертификатов и ключей из keystore в формате PKCS#12 (.pfx, .p12);
- PemUtils.java - утилиты для работы с PEM форматом;
- SignAlgorithm.java - поддерживаемые алгоритмы подписания;
- VerifyAlgorithm.java - поддерживаемые алгоритмы верификации подписи;
- pem - работа с PEM форматом;
- PemObject.java - объект из файла формата PEM;
- PemReader.java - парсер PEM файла;
- http - классы, связанные с оберткой HTTP клиента;
- ApacheHttpClient.java - реализация HTTP клиента (Apache);
- Constants.java - различные константы, используемые с протоколом HTTP;
- FormUrlCoder.java - формирование URL-encoded строки запроса;
- HttpClient.java - интерфейс HTTP клиента;
- HttpClientLogWrapper.java - прокси, который логирует HTTP запросы, проходящие через HTTP клиент;
- HttpMethod.java - HTTP методы;
- HttpRequest.java - HTTP запрос;
- HttpResponse.java - HTTP ответ;
- Pair.java - пара “ключ-значение”;
- Params.java - список параметров “ключ-значение”;
- logging - классы для логирования;
- LoggerDelegate.java - делегат логирования;
- Logger.java - внутренний класс. Логгер, который использует предоставленный делегат для вывода сообщений;
- LogLevel.java - уровни логирования;
- utils - вспомогательные классы;
- ArrayUtils.java - вспомогательные функции для массивов;
- AuthorizationRequiredException.java - исключение, сообщающее о необходимости авторизоваться;
- BaseException.java - базовый класс исключений библиотеки;
- DateTimeGsonDeserializer.java - десериализатор даты и времени, приходящих от ЕСИА;
- ParameterRequiredException.java - исключение о требуемом параметре;
- Request.java - Адаптер к объекту запроса платформы приложения. Приложение использует некий фреймворк или библиотеку для обработки входящих HTTP запросов. Данный адаптер позволяет из HTTP запроса платформы получить некоторую информацию;
- bouncycastle
- BCCryptoProvider.java - провайдер, обеспечивающий создание крипто-сервиса на базе крипто-библиотеки BouncyCastle. Также предоставляет вспомогательные механизмы для загрузки ключей и сертификатов;
- BCCryptoService.java - реализация крипто-сервиса на базе крипто-библиотеки BouncyCastle;
3 Основные функции
Основными функциями библиотеки авторизации являются:
- получение авторизационного кода ЕСИА;
- обмен авторизационного кода на маркер доступа;
- обмен маркера обновления на маркер доступа (без запроса авторизации пользователя на стороне ЕСИА);
- получение дополнительных разрешений в процессе работы и переавторизация в ЕСИА при необходимости;
- получение данных пользователя из ЕСИА (в приложении Б перечислены скоупы, которые может получать базовая и расширенная версии библиотеки);
- выход (логаут) на стороне ЕСИА;
- подписание запросов к ЕСИА на основе криптографических средств, установленных на удалённом сервере.
4 Интеграция библиотеки
4.1 Подготовка
Перед началом интеграции необходимо:
- настроить для вашей системы HTTPS (это обязательное требование, поскольку данные между вашей системой и ЕСИА передаются в открытом виде);
- выполнить экспорт ключевой пары (сформированной по ГОСТ2012) из криптоконтейнера (экспорт можно сделать с помощью нашей утилиты);
- настроить систему на технологическом портале тестовой/промышленной ЕСИА. На технологическом портале в окне редактирования параметров системы (см. рисунок 1) указать URL возврата после авторизации и логаута, а также установить алгоритм подписания запросов GOST3410_2012_256.
Рисунок 1 - Поля в окне редактирования параметров системы
- В подходящую директорию положить ключ и сертификат в PEM формате (для извлечения ключа и сертификата из криптоконтейнера можно воспользоваться нашей утилитой), сформированные по ГОСТ2012 с длиной ключа 256 бит, и удостовериться, что тот же сертификат загружен на технологическом портале тестовой/промышленной ЕСИА.
- В подходящую директорию положить файл сертификата ЕСИА в PEM формате с именем esia-test.crt или esia-prod.crt в зависимости от окружения (тестовое/промышленное), в котором запускается код.
- ВАЖНО!!! Настроить доступ к директориям для размещения файлов сертификата, ключа и логов библиотеки таким образом, чтобы их файлы нельзя было получить извне.
4.2 Подключение библиотеки к проекту
Поскольку библиотека поставляется в виде модулей с открытым исходным кодом она может быть интегрирована в кодовую базу любого проекта на Java (при соблюдении требований к зависимостям, которые описаны в разделе 5).
Возможны следующие варианты подключения библиотеки к целевому проекту:
- Сборка библиотеки и деплой в репозиторий Maven, подключение к целевому проекту на базе Maven или Gradle в виде зависимости;
- Сборка библиотеки в jar и подключение к целевому проекту;
- Копирование необходимых файлов исходников и добавление их в целевой проект; ### 4.2.1. Сборка библиотеки и деплой в репозиторий Maven Данный вариант подходит для любых проектов, основанных на Maven либо Gradle.
Необходимые шаги по подключению:
- Сборка и публикация:
- Публикация в локальный репозиторий разработчика:
./gradlew publishToMavenLocal
- Публикация в приватный репозиторий
./gradlew publish -Ppublish.username=”username” -Ppublish.password=”password” -Ppublish.url=”https://maven.example.com/repo”
- Добавить в проект зависимость в секцию dependencies:
- Для Maven (pom.xml):
<dependency>
<groupId>ru.rnds.esia</groupId>
<artifactId>esia-oauth2-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>ru.rnds.esia</groupId>
<artifactId>esia-oauth2-bouncycastle</artifactId>
<version>2.0</version>
</dependency>
- Для Gradle Groovy (build.gradle):
implementation ‘ru.rnds.esia:esia-oauth2-core:2.0’
implementation ‘ru.rnds.esia:esia-oauth2-bouncycastle:2.0’
- Для Gradle Kotlin (build.gradle.kts):
implementation(“ru.rnds.esia:esia-oauth2-core:2.0”)
implementation(“ru.rnds.esia:esia-oauth2-bouncycastle:2.0”)
4.2.2 Сборка библиотеки в jar и подключение к целевому проекту;
- В корне целевого проекта необходимо создать папку libs
- Сборка и публикация библиотек в локальный репозиторий maven в папке libs:
cd esia-oauth2-java
./gradlew -Dmaven.repo.local=/home/user/project/libs publishToMavenLocal
- Подключение к проекту:
- Maven (pom.xml):
<repositories>
<repository>
<id>local</id>
<url>file://${project.basedir}/libs</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ru.rnds.esia</groupId>
<artifactId>esia-oauth2-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>ru.rnds.esia</groupId>
<artifactId>esia-oauth2-bouncycastle</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
- Gradle Groovy (build.gradle):
repositories {
mavenLocal {
url "file://${rootProject.rootDir}/libs"
}
mavenCentral()
}
dependencies {
implementation 'ru.rnds.esia:esia-oauth2-core:2.0'
implementation 'ru.rnds.esia:esia-oauth2-bouncycastle:2.0'
}
- Gradle Kotlin (build.gradle.kts):
repositories {
mavenLocal {
setUrl("file://${rootProject.rootDir}/libs")
}
mavenCentral()
}
dependencies {
implementation("ru.rnds.esia:esia-oauth2-core:2.0")
implementation("ru.rnds.esia:esia-oauth2-bouncycastle:2.0")
}
4.2.3 Добавление файлов исходников в целевой проект
В данном варианте подключения предусматривается простое копирование всех необходимых исходников библиотеки в целевой проект в любую папку в src/main/java на усмотрение разработчика.
4.3. Реализация необходимых интеграционных классов
Необходимо реализовать следующие интерфейсы:
- AuthStateStorage - интерфейс хранилища авторизационных данных
- Request - адаптер к объекту запроса платформы / фреймворка приложения
- LoggerDelegate - делегат логирования (не обязательно)
- HttpClient - HTTP клиент (не обязательно)
AuthStateStorage
При выполнении каждого запроса необходимо получить авторизационные данные, такие как маркер доступа, маркер обновления маркера доступа. Также в процессе запроса маркеры могут быть обновлены и их необходимо сохранить для выполнения последующих запросов. Для этих целей предназначен этот интерфейс. Реализация может хранить данные в сессии пользователя, либо в любом другом хранилище (БД). Важно реализовать механизм блокировки хранилища, так как запросы могут выполняться параллельно и может возникнуть ситуация когда два параллельных запроса начнут одновременно обновлять маркер доступа. Без блокировки последний запрос получит ошибку AuthorizationRequiredException.
Пример реализации данного интерфейса при работе с механизмом сервлетов находится в демонстрационном приложении по пути: sample-app/src/main/java/ru/rndsoft/esia/oauth2/sampleapp/utils/ServletAuthStateStorage.java.
Request
При обработке запроса от ЕСИА об успешной авторизации (handleLoginRedirect) необходимо получение определённых параметров из запроса. Данный интерфейс адаптирует запрос платформы (ServletRequest) для библиотеки.
Пример реализации данного интерфейса при работе с механизмом сервлетов находится в демонстрационном приложении по пути: sample-app/src/main/java/ru/rndsoft/esia/oauth2/sampleapp/utils/ServletRequest.java.
LoggerDelegate
Позволяет реализовать и сконфигурировать извне необходимый механизм логирования сообщений библиотеки.
Пример реализации данного интерфейса при работе с SLF4J находится в демонстрационном приложении по пути: sample-app/src/main/java/ru/rndsoft/esia/oauth2/sampleapp/utils/Slf4JLoggerDelegate.java.
HttpClient
Библиотека использует встроенный Apache HTTP клиент, но при необходимости возможно добавить реализацию основанную на любом другом HTTP клиенте, на том например, который используется в целевом проекте.
Интерфейс HTTP клиента библиотеки находится в core/src/main/java/ru/rndsoft/esia/http/HttpClient.java.
Реализация Apache HTTP клиента находится в core/src/main/java/ru/rndsoft/esia/http/ApacheHttpClient.java.
4.4 Инициализация библиотеки
Способ инициализации зависимостей зависит от используемого фреймворка или платформы целевого приложения. Рассмотрим инициализацию на примере сервлетов.
В результате инициализации будут получены настроенные классы EsiaAuthService и PersonInfoService при помощи которых в дальнейшем будут производиться действия по авторизации и получению персональных данных.
Функциональность формирования запроса авторизации, получения маркера доступа и обновление маркера доступа по различным алгоритмам вынесена в отдельные классы.
Формирование запроса авторизации производится классами LoginUrlBuilderV1 (API v1) и LoginUrlBuilderV2 (API v2), которые реализуют интерфейс LoginUrlBuilder. На данный момент актуальным является API v2. API v1 считается устаревшим и не рекомендуется к использованию.
Получение маркера доступа производится классами AccessTokenRequesterV1 (API v1) и AccessTokenRequesterV3 (API v3), которые реализуют интерфейс AccessTokenRequester. На данный момент актуальным является API v3. API v1 считается устаревшим и не рекомендуется к использованию.
Обновление маркера доступа производится классом AccessTokenRefresherV1 (API v1), который реализуют интерфейс AccessTokenRequester.
Инициализация производится в классе StartStopListener в методе contextInitialized (sample-app/src/main/java/ru/rndsoft/esia/oauth2/sampleapp/StartStopListener.java):
// создаем SLF4J адаптер логов
Slf4JLoggerDelegate loggerDelegate = new Slf4JLoggerDelegate();
String baseUrl = getEnv("BASE_URL", "http://localhost:8080");
// создаем крипто-провайдер BouncyCastle
BCCryptoProvider provider = new BCCryptoProvider();
FileCertLoader fileCertLoader = provider.createFileCertLoader();
// загружаем сертификат ЕСИА для валидации маркера доступа
X509Certificate esiaCert = loadEsiaCert(fileCertLoader);
// Загружаем сертификат и ключ клиента
CertWithKey clientCertWithKey = fileCertLoader.loadCertWithKey(
requireEnv("CERT_FILE"),
requireEnv("KEY_FILE")
);
// Создаем крипто-сервис
CryptoService cryptoService = provider.createService(clientCertWithKey, esiaCert);
// Создаем валидатор маркера доступа
AccessTokenVerifier accessTokenVerifier = null;
if (esiaCert != null) {
accessTokenVerifier = new EsiaTokenVerifier(cryptoService);
}
// Создаем объект конфигурации
configuration = Configuration.builder()
// используем тестовый домен ЕСИА
.domain(EsiaDomain.TEST)
// задаём путь нашего обработчика редиректа из ЕСИА при авторизации
.loginRedirectUri(String.format("%s/oauth2/login_response", baseUrl))
// задаём путь нашего обработчика редиректа из ЕСИА при выходе
.logoutRedirectUri(String.format("%s/oauth2/logout_success", baseUrl))
// задаём нашу мнемонику в ЕСИА
.clientId(requireEnv("CLIENT_ID"))
// задаём необходимые scope для доступа к данным
.scopes(Scope.FULLNAME, Scope.ID_DOC, Scope.INN, Scope.SNILS, Scope.ADDRESSES,
Scope.VEHICLES, Scope.USR_ORG, Scope.EMAIL, Scope.MOBILE,
Scope.KID_FULLNAME, Scope.KID_BIRTHDATE, Scope.KID_INN, Scope.KID_SNILS,
Scope.KID_GENDER, Scope.KID_BIRTH_CERT_DOC, Scope.KID_MEDICAL_DOC)
// задаём тип доступа к данным
.accessType(AccessType.ONLINE)
// используем созданный крипто-сервис
.cryptoService(cryptoService)
// используем созданный верификатор кода доступа
.accessTokenVerifier(accessTokenVerifier)
// используем созданный логгер для логирования вывода библиотеки
.loggerDelegate(loggerDelegate)
.build();
// создаём сервис авторизации с указанием реализаций формирования запроса авторизации, получения
// авторизационных данных по коду и обновление маркера доступа
AuthService authService = new EsiaAuthService(configuration, new LoginUrlBuilderV2(),
new AccessTokenRequesterV3(), new AccessTokenRefresherV1());
// создаём сервис получения персональной информации пользователя
PersonInfoService personInfoService = new PersonInfoService(configuration, authService);
По окончании работы приложения рекомендуется закрыть конфигурацию, при этом будут освобождаться занятые ресурсы и удаляться временные файлы. Закрытие производится в классе StartStopListener в методе contextDestroyed:
configuration.close();
4.5 Процесс авторизации в ЕСИА
Получение URL для прохождения авторизации производится вызовом метода createLoginRequest интерфейса AuthService. В результате (LoginRequest) помимо uri также возвращается state (ID состояния запроса), который следует сохранить в сессии пользователя для дальнейшей проверки запроса на возможные атаки CSRF. Если такая проверка не нужна, полученный state можно проигнорировать.
Пример реализации на сервлетах находится в классе LoginServlet:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AuthService service = ServiceLocators.authService.get(getServletContext());
LoginRequest loginRequest = service.createLoginRequest();
HttpSession session = request.getSession(true);
session.setAttribute("state", loginRequest.state);
response.sendRedirect(loginRequest.uri);
}
После завершения авторизации ЕСИА производит перенаправление на сконфигурированный путь возврата (loginRedirectUri) в котором передает дополнительными параметрами необходимые данные для завершения процесса авторизации на стороне приложения. Обработка данных завершения производится вызовом метода handleLoginRedirect интерфейса AuthService.
Дополнительно, если используется проверка на CSRF, необходимо восстановить идентификатор состояния запроса (state), ранее сохраненный в сессии пользователя, и передать его в вызов метода handleLoginRedirect. Если проверка на CSRF не требуется, в state передается null.
Пример реализации на сервлетах находится в классе OnLoginResponseServlet:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AuthService service = ServiceLocators.authService.get(getServletContext());
HttpSession session = request.getSession();
String stateFromSession = (String) session.getAttribute("state");
try {
service.handleLoginRedirect(new ServletRequest(request), new ServletAuthStateStorage(session), stateFromSession);
} catch (EsiaException e) {
throw new RuntimeException(e);
}
if (AdditionalScopeRequester.handleRedirectAfterLogin(request, response))
return;
response.sendRedirect("/person_info");
}
4.6 Выход из ЕСИА
Получение URL для выхода (логаута) пользователя производится методом createLogoutUrl интерфейса AuthService. Для выхода следует перенаправить пользователя на полученный URL, также стоит зачистить объект сессии пользователя.
Пример реализации запуска процесса выхода находится в классе LogoutServlet:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AuthService service = ServiceLocators.authService.get(getServletContext());
HttpSession session = request.getSession();
if (session != null)
session.invalidate();
String logoutUrl = service.createLogoutUrl();
response.sendRedirect(logoutUrl);
}
После завершения процесса выхода ЕСИА производит перенаправление на сконфигурированный путь возврата (logoutRedirectUri). Обработка завершения производится вызовом метода handleLogoutRedirect интерфейса AuthService.
Пример реализации на сервлетах находится в классе OnLogoutSuccessServlet:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AuthService service = ServiceLocators.authService.get(getServletContext());
service.handleLogoutRedirect(new ServletAuthStateStorage(request.getSession()));
request.getRequestDispatcher("/logout_success.jsp").forward(request, response);
}
4.7 Обновление маркера доступа
Маркер доступа обновляется автоматически при любых запросах маркера доступа методами getAccessToken или requireAccessToken интерфейса AuthService. Для принудительного обновления маркера доступа используется метод refreshAccessToken. Стоит отметить, что в продуктовой эксплуатации явный вызов этого метода не требуется, он предназначен исключительно для тестирования.
Пример реализации обновления маркера доступа находится в классе OnRefreshTokenServlet:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AuthService service = ServiceLocators.authService.get(getServletContext());
HttpSession session = request.getSession();
try {
service.refreshAccessToken(new ServletAuthStateStorage(session));
} catch (AuthorizationRequiredException e) {
throw new RuntimeException(e);
}
response.sendRedirect("/person_info");
}
4.8 Получение дополнительных разрешений
Для получения некоторых наборов данных необходимо получение дополнительных разрешений с указанием идентификаторов полученных в процессе запросов (например при запросе детальной информации об организации). Для этих целей служит метод requestScopes в интерфейсе AuthService.
При запросе доп. разрешений в случае, если у пользователя ещё этих разрешений нет, формируется URL на прохождении авторизации. Приложению следует перенаправить пользователя на этот URL. Далее процесс проходит аналогично с обычной авторизацией.
Пример реализации запроса дополнительных разрешений находится в классе AdditionalScopeRequester:
public static boolean request(AuthService authService,
AuthStateStorage storage,
HttpServletRequest request,
HttpServletResponse response,
String... scopes) throws AuthorizationRequiredException, IOException {
@Nullable LoginRequest loginRequest = authService.requestScopes(storage, scopes);
if (loginRequest == null) return false;
HttpSession session = request.getSession();
String uri = request.getRequestURI();
String query = request.getQueryString();
if (query != null && !query.isEmpty()) {
uri = uri + "?" + query;
}
session.setAttribute(REDIRECT_AFTER_LOGIN_ATTR, uri);
session.setAttribute("state", loginRequest.state);
response.sendRedirect(loginRequest.uri);
return true;
}
Пример использования AdditionalScopeRequester находится в классе OrgDetailsServlet:
if (AdditionalScopeRequester.request(authService, storage, request, response,
Stream.of(Scope.ORG_FULLNAME, Scope.ORG_SHORTNAME, Scope.ORG_ADDRS, Scope.ORG_TYPE,
Scope.ORG_OGRN, Scope.ORG_INN, Scope.ORG_KPP, Scope.ORG_LEG, Scope.ORG_AGENCYTYPE,
Scope.ORG_EMPS, Scope.ORG_BRHS
).map(s -> s.addParam("org_oid", orgId)).collect(Collectors.toList())
)) return;
4.9 Получение персональных данных
За получение персональных данных отвечает класс PersonInfoService. Данный сервис предоставляет следующие методы для получения данных:
- getPersonId - получение идентификатора пользователя;
- getPersonInfo - получение персональной информации (ФИО, СНИЛС, гражданство, пол, дату, место рождения и т.д.);
- getPersonDocuments - документы пользователя (паспорт, водительские права и т.д.);
- getPersonContacts - контактные данные пользователя (телефон, email);
- getPersonOrgs - сводные данные об организациях, сотрудником которых является пользователь;
- getPersonAddesses - список адресов пользователя;
- getPersonKids - перечень записей о детях физ. лица;
- getPersonKidDocuments - список документов ребенка;
- getPersonVehicles - список зарегистрированных транспортных средств пользователя;
- getOrgDetails - получение детальной информации об организации пользователя. Необходимо получение дополнительного разрешения.
Пример получения информации находится в классах PersonInfoServlet:
AuthService authService = ServiceLocators.authService.get(request.getServletContext());
ServletAuthStateStorage storage = new ServletAuthStateStorage(request.getSession());
PersonInfoService personInfoService = ServiceLocators.personInfoService.get(request.getServletContext());
PersonInfoService.Requester requester = personInfoService.getRequester(storage);
String personId = requester.getPersonId();
PersonInfo personInfo = requester.getPersonInfo(personId);
PersonDocument[] documents = requester.getPersonDocuments(personId);
PersonContact[] contacts = requester.getPersonContacts(personId);
PersonAddress[] addresses = requester.getPersonAddresses(personId);
PersonKid[] kids = requester.getPersonKids(personId);
Map<String, PersonDocument[]> kidsDocuments = Arrays.stream(kids).collect(Collectors.toMap(PersonKid::getId, k -> {
try {
return requester.getPersonKidDocuments(personId, k.getId());
} catch (IOException | AuthorizationRequiredException | EsiaException e) {
throw new RuntimeException(e);
}
}));
PersonVehicle[] vehicles = requester.getPersonVehicles(personId);
PersonOrg[] orgs = requester.getPersonOrgs(personId);
request.setAttribute("personInfo", personInfo);
request.setAttribute("contacts", contacts);
request.setAttribute("documents", documents);
request.setAttribute("addresses", addresses);
request.setAttribute("kids", kids);
request.setAttribute("kidsDocuments", kidsDocuments);
request.setAttribute("vehicles", vehicles);
request.setAttribute("personOrgs", orgs);
request.setAttribute("authState", gson.toJson(storage.getState(), AuthState.class));
request.setAttribute("scopes", authService.getScopes(storage));
request.getRequestDispatcher("/person_info.jsp").forward(request, response);
И OrgDetailsServlet:
PersonInfoService personInfoService = ServiceLocators.personInfoService.get(request.getServletContext());
PersonInfoService.Requester requester = personInfoService.getRequester(storage);
OrgDetails orgDetails = requester.getOrgDetails(orgId);
request.setAttribute("orgDetails", orgDetails);
request.getRequestDispatcher("/org_details.jsp").forward(request, response);
5 Зависимости
Библиотека авторизации предъявляет следующие языковые требования
Java >= 8
Также в случае интеграции с копированием исходников в проект (п. 4.2.3) для работы библиотеки авторизации должны быть прописаны следующие зависимости:
- org.jetbrains:annotations:16.0.2
- org.apache.httpcomponents:httpclient:4.5.13
- com.auth0:java-jwt:4.0.0
- com.google.code.gson:gson:2.9.1
- org.bouncycastle:bcprov-jdk18on:1.72
- org.bouncycastle:bcpkix-jdk18on:1.72
ПРИЛОЖЕНИЕ А.
Описание конфигурационных параметров
Библиотека авторизации принимает на вход набор параметров (класс Configuration), описанных в таблице А.1.
Таблица А.1. - Описание параметров
№ | Наименование параметра | Обязательный | Описание параметра |
---|---|---|---|
1 | domain | да | URL системы - поставщика услуг (ЕСИА) |
2 | clientId | да | Мнемоника, полученная при регистрации ИС в минкомсвязи |
3 | loginRedirectUri | да | Определяет адрес возврата в ИС после авторизации пользователя в ЕСИА |
4 | logoutRedirectUri | нет | Определяет адрес возврата в ИС после логаута пользователя в ЕСИА |
5 | scopes, customScopes | нет | Перечень областей данных, к которым предоставляется доступ для ИС после авторизации |
6 | accessType | да | Определяет тип доступа к защищенному хранилищу ЕСИА предоставляемому для ИС |
7 | accessTokenVerifier | нет | Определяет реализацию проверки маркера доступа |
8 | loggerDelegate | нет | Определяет реализацию логирования |
9 | dateProvider | нет | Определяет реализацию поставщика текущего времени |
10 | stateGenerator | нет | Определяет реализацию генератора идентификаторов для state |
11 | httpClient | нет | Определяет реализацию HttpClient |
12 | cryptoService | да | Определяет крипто-сервис |
Пример формирования конфигурационного объекта, задающего необходимый набор параметров для библиотеки, приведен ниже.
Для тестовой среды ЕСИА:
// Создаем объект конфигурации
configuration = Configuration.builder()
// используем тестовый домен ЕСИА
.domain(EsiaDomain.TEST)
// задаём путь нашего обработчика редиректа из ЕСИА при авторизации
.loginRedirectUri(String.format("%s/oauth2/login_response", baseUrl))
// задаём путь нашего обработчика редиректа из ЕСИА при выходе
.logoutRedirectUri(String.format("%s/oauth2/logout_success", baseUrl))
// задаём нашу мнемонику в ЕСИА
.clientId(requireEnv("CLIENT_ID"))
// задаём необходимые scope для доступа к данным
.scopes(Scope.FULLNAME, Scope.ID_DOC, Scope.INN, Scope.SNILS, Scope.ADDRESSES,
Scope.VEHICLES, Scope.USR_ORG, Scope.EMAIL, Scope.MOBILE,
Scope.KID_FULLNAME, Scope.KID_BIRTHDATE, Scope.KID_INN, Scope.KID_SNILS,
Scope.KID_GENDER, Scope.KID_BIRTH_CERT_DOC, Scope.KID_MEDICAL_DOC)
// задаём тип доступа к данным
.accessType(AccessType.ONLINE)
// используем созданный крипто-сервис
.cryptoService(cryptoService)
// используем созданный верификатор кода доступа
.accessTokenVerifier(accessTokenVerifier)
// используем созданный логгер для логирования вывода библиотеки
.loggerDelegate(loggerDelegate)
.build();
Для промышленной среды ЕСИА:
// Создаем объект конфигурации
configuration = Configuration.builder()
// используем продуктовый домен ЕСИА
.domain(EsiaDomain.PROD)
// задаём путь нашего обработчика редиректа из ЕСИА при авторизации
.loginRedirectUri(String.format("%s/oauth2/login_response", baseUrl))
// задаём путь нашего обработчика редиректа из ЕСИА при выходе
.logoutRedirectUri(String.format("%s/oauth2/logout_success", baseUrl))
// задаём нашу мнемонику в ЕСИА
.clientId(requireEnv("CLIENT_ID"))
// задаём необходимые scope для доступа к данным
.scopes(Scope.FULLNAME, Scope.ID_DOC, Scope.INN, Scope.SNILS, Scope.ADDRESSES,
Scope.VEHICLES, Scope.USR_ORG, Scope.EMAIL, Scope.MOBILE,
Scope.KID_FULLNAME, Scope.KID_BIRTHDATE, Scope.KID_INN, Scope.KID_SNILS,
Scope.KID_GENDER, Scope.KID_BIRTH_CERT_DOC, Scope.KID_MEDICAL_DOC)
// задаём тип доступа к данным
.accessType(AccessType.ONLINE)
// используем созданный крипто-сервис
.cryptoService(cryptoService)
// используем созданный верификатор кода доступа
.accessTokenVerifier(accessTokenVerifier)
// используем созданный логгер для логирования вывода библиотеки
.loggerDelegate(loggerDelegate)
.build();
ПРИЛОЖЕНИЕ Б.
Перечень запрашиваемых областей доступа
Перечень областей данных (scope) библиотеки приведен в таблице Б.1.
Таблица Б.1. - Перечень запрашиваемых областей доступа
№ | Название scope | Состав набора данных | Запрашивается(+)/Не запрашивается(-) |
---|---|---|---|
1. | fullname | Просмотр фамилии, имени и отчества: • фамилия; • имя; • отчество. |
+ |
2. | birthdate | дата рождения, указанная в учетной записи | + |
3. | gender | пол, указанный в учетной записи | + |
4. | snils | СНИЛС, указанный в учетной записи | + |
5. | inn | ИНН, указанный в учетной записи | + |
6. | id_doc | Просмотр данных о документе, удостоверяющем личность: • серия и номер документа, удостоверяющего личность; • дата выдачи; • кем выдан; • код подразделения; • гражданство. |
+ |
7. | birthplace | место рождения. | + |
8. | medical_doc | Просмотр данных полиса ОМС: • номер полиса ОМС; • срок действия. |
+ |
9. | military_doc | Просмотр данных военного билета: • серия и номер военного билета; • дата выдачи; • орган, выдавший документ. |
+ |
10. | foreign_passport_doc | Просмотр данных заграничного паспорта: • фамилия, имя, отчество буквами латинского алфавита; • серия и номер заграничного паспорта; • дата выдачи; • срок действия; • орган, выдавший документ; • гражданство. |
+ |
11. | drivers_licence_doc | Просмотр данных водительского удостоверения: • серия и номер водительского удостоверения; • дата выдачи; • срок действия. |
+ |
12. | birth_cert_doc | Просмотр данных свидетельства о рождении: • серия и номер свидетельства; • дата выдачи; • место государственной регистрации. |
+ |
13. | residence_doc | Просмотр данных вида на жительство: • серия и номер вида на жительство; • дата выдачи. |
+ |
14. | temporary_residence_doc | Просмотр данных разрешения на временное проживание: • серия и номер разрешения на временное проживание; • дата выдачи. |
+ |
15. | vehicles | Просмотр данных транспортных средств: • государственный регистрационный знак; • серия и номер свидетельства о регистрации. |
+ |
16. | адрес электронной почты, указанный в учетной записи | + | |
17. | mobile | номер мобильного телефона | + |
18. | contacts | Просмотр данных о контактах и адресах: • номер домашнего телефона; • номер мобильного телефона; • адрес электронной почты; • адрес регистрации; • адрес места проживания. |
+ |
19. | usr_org | список организаций пользователя. | + |
20. | usr_avt | Просмотр изображения (аватара) пользователя: • получения изображения (аватара); • создание и обновление изображения (аватара); • получение исходного изображения (аватара) |
- |
21. | self_employed | Просмотр данных о самозанятых • признак самозанятого; • категория (вид деятельности). |
- |
22. | kid_fullname | Просмотр фамилии, имени и отчества: • фамилия; • имя; • отчество. |
+ |
23. | kid_birthdate | дата рождения ребенка | + |
24.. | kid_gender | Пол ребенка | + |
25. | kid_snils | СНИЛС ребенка | + |
26. | kid_inn | ИНН ребенка | + |
27. | kid_birth_cert_doc | Просмотр данных свидетельства о рождении: • серия свидетельства; • номер свидетельства; • дата выдачи свидетельства; • кем выдано свидетельство. |
- |
28. | kid_medical_doc | Просмотр данных полиса ОМС: • номер полиса ОМС; • действителен до ОМС. |
- |
1. | org_shortname | Сокращенное наименованиеорганизации | + |
2. | org_fullname | Полное наименованиеорганизации | + |
3. | org_type | Тип организации | + |
4. | org_ogrn | ОГРН организации | + |
5. | org_inn | ИНН организации | + |
6. | org_leg | ОПФ организации | + |
7. | org_kpp | КПП организации | + |
8. | org_agencyterrange | Территориальнаяпринадлежность ОГВ | + |
9. | org_agencytype | Тип ОГВ | + |
10. | org_oktmo | ОКТМО организации | + |
11. | org_ctts | Контакты организации: номер телефона, номер факса, адрес электронной почты | + |
12. | org_addrs | Адреса организации (почтовый адрес, юридический адрес): индекс, идентификатор страны, адрес в виде строки (не включая дом, строение, корпус, номер квартиры), строение, корпус, дом, квартира, код ФИАС, регион,город, внутригородской район, район, поселение, доп. территория, улица на доп. территории, улица | + |
13. | org_vhls | Транспортные средства организации: название, государственный регистрационный знак, серия и номер свидетельства орегистрации | - |
14. | org_grps | Группы, владельцемкоторых является организация | - |
15. | org_emps | Данные о сотрудникахорганизации | - |
16. | org_brhs | Данные о филиалах организации (название, КПП, ОПФ, контакты,адреса) | - |
17. | org_brhs_ctts | Контакты филиаловорганизации | - |
18. | org_brhs_addrs | Адреса филиаловорганизации | - |
19. | org_rcs | Центры регистрацииорганизации | - |
20. | org_stms | Системы, владельцемкоторых является организация | - |
21. | org_invts | Приглашения, направленныеорганизацией | - |
22. | categories | Данные присвоенных организации видовдеятельности | - |