Проверка аутентификации в прикладном приложении
Аутентификация в прикладных приложениях происходит с помощью JWT-токена в заголовке
Authorization
. Для проверки и получения данных из JWT-токенов применяются фильтры аутентификации для Spring-Security:plat-jwt-authentication-starter
— выполняет проверку JWT-токена и создает объектAuthenitcation
в прикладном приложении. Этот фильтр используется для эксплуатации в ПРОМ-среде;plat-stumb-jwt-authentication-starter
— создает объектAuthenitcation
и JWT-токены при обращении к прикладному приложению на основе файлов профилей. Этот фильтр используется для локального запуска и для режима отладки на DEV-стендах.
Доступ к стенду и подключение к интернету необходимы для работы как с фильтром для ПРОМ-стенда, так и с фильтром для локального запуска.
Подключение аутентификации в Java-приложениях
При разработке java-приложений рекомендуется подключать оба фильтра аутентификации и переключаться между ними с помощью Spring-профилей.
Для подключения фильтров:
-
Проверьте наличие подключенного maven-репозитория в
.m2/settings.xml
:settings.xml type=xml<servers> <server> <id>cpr_maven</id> <username>ИМЯ УЧЕТНОЙ ЗАПИСИ В SBER CLOUD</username> <password>ПАРОЛЬ УЧЕТНОЙ ЗАПИСИ В SBER CLOUD</password> </server> </servers> <profiles> <profile> <id>default</id> <repositories> <repository> <id>cpr_maven</id> <url>https://Путь_до_зависимостей_в_нексусе</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <profile> <profiles>
-
Добавьте зависимость с контрактами в
pom.xml
:
-
для spring-webmvc:pom.xml type=xml
<dependency> <groupId>ru.sbrf.ufs.platform</groupId> <artifactId>plat-jwt-authentication-starter</artifactId> <version>3.1.9</version> </dependency> <dependency> <groupId>ru.sbrf.ufs.platform</groupId>ы <artifactId>plat-stumb-jwt-authentication-starter</artifactId> <version>3.3.1</version> </dependency>
-
для spring-webflux:pom.xml type=xml
<dependency> <groupId>ru.sbrf.ufs.platform</groupId> <artifactId>plat-jwt-authentication-starter-webflux</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>ru.sbrf.ufs.platform</groupId> <artifactId>plat-stumb-jwt-authentication-starter-webflux</artifactId> <version>3.3.1</version> </dependency>
-
Добавьте в
application.yml
настройки для фильтров аутентификации.-
auth
- настройка фильтраplat-jwt-authentication-starter
для ПРОМ-среды:urls
— массив доверенных URL Keycloak, JWT-токены которых считаются валидными. Токены валидируются по полюISSUER
с проверкой вида «начинается с»;keysLifetime
— время жизни публичного ключа проверки токена в локальном хранилище фильтра аутентификации;sslIgnore
— флаг пропуска валидации сертификатов SSL при обращении к IAM Keycloak для получения публичных ключей. Эта настройка опциональна, рекомендуется использовать ее только на DEV-стендах.
-
localauth
— настройка фильтраplat-stumb-jwt-authentication-starter
для локального запуска:profilesDir
— путь до папки с профилями. Может быть абсолютным или относительным от корня проекта;defaultProfile
— название профиля по умолчанию: название файла (без расширения) в папке с профилями;ufsProviderUrl
— URL для генерации JWT-токена и сессии пользователя в UFS Provider. JWT-токен генерируется на основе json-профиля, созданного в прикладном приложении.
Для ПРОМ-стенда в cреде Platform V Kubernetes:application.yml type=ymlauth: urls: - <ISSUER address> # адрес ISSUER из JWT-токена authorizeUrl: http://platform-gateway/ufs-security # сервис получения permissions (оставить пустым, если у вас в приложении нет проверки на методах @PreAuthorize или @ReactivePermissionCheck) sslIgnore: true # если нужно игнорировать https useHttpIAM: true # меняет Https на Http при обращении в IAM useIAMPort: 7070 # меняет/добавляет порт 7070 при обращении в IAM supportMultitenancy: true # значение должно быть true, т.к. platform-gateway и mtp-gateway переписывают мультитенантный эндпойнт keycloak: sslIgnore: true # если нужно игнорировать https useHttpIAM: true # меняет Https на Http при обращении в IAM useIAMPort: 7070 # меняет/добавляет порт 7070 при обращении в IAM localauth: profilesDir: profiles defaultProfile: 2 ufsProviderUrl: http://platform-gateway/ufs-provider
Для тестирования в локальном окружении ({адрес_ingress}
- берется из паспорта стенда):application.yml type=ymlauth: urls: - <ISSUER address> # адрес ISSUER из JWT-токена authorizeUrl: http://{адрес_ingress}/ufs-security # сервис получения permissions (оставить пустым, если у вас в приложении нет проверки на методах @PreAuthorize или @ReactivePermissionCheck) sslIgnore: true # если нужно игнорировать https supportMultitenancy: true # значение должно быть true, т.к. platform-gateway и mtp-gateway переписывают мультитенантный эндпойнт keycloak: sslIgnore: true # если нужно игнорировать https localauth: profilesDir: profiles defaultProfile: 2 ufsProviderUrl: http://{адрес_ingress}/ufs-provider
-
-
Создайте класс
SecurityConfiguration
. Он позволяет настроить уровень доступности методов и включить дополнительные настройки безопасности, например, CSRF, CORS.В этом же классе настраивается переключение фильтров аутентификации: чтобы переключиться на локальный фильтр, добавьте Spring-профильinternal
.В таблице ниже представлены соответствие поддерживаемых минимальные версии spring-boot фильтрам аутентификации:Фильтр spring-boot 3.X.X spring-boot 2.X.X plat-jwt-authentication-starter3.3.0 all plat-stumb-jwt-authentication-starter3.3.0 all java17 all SecurityConfig.java type=javapackage ru.sbrf.ufs.platform.security.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import ru.sbrf.ufs.platform.jwt.authentication.filter.JwtSecurityConfigurerAdapter; import ru.sbrf.ufs.platform.stumb.jwt.authentication.filter.StumbJwtSecurityConfigurerAdapter; import org.springframework.core.env.Environment; import java.util.Arrays; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired JwtSecurityConfigurerAdapter jwtSecurityConfigurerAdapter; @Autowired StumbJwtSecurityConfigurerAdapter stumbJwtSecurityConfigurerAdapter; @Autowired Environment env; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { boolean isLocal = Arrays.asList(env.getActiveProfiles()).contains("internal"); //@formatter:off http .httpBasic().disable() .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/anonym/**").permitAll() .antMatchers("/anonym").permitAll() .anyRequest().authenticated() .and() .apply(isLocal?stumbJwtSecurityConfigurerAdapter:jwtSecurityConfigurerAdapter); //@formatter:on } }
Библиотека позволяет полностью пропускать фильтр аутентификации для запросов, которым она не требуется (например, swagger и healthcheck). Для этого в классе настройщика безопасности нужно определить методpublic void configure(WebSecurity web) throws Exception
и указать нужные запросы в спискеignoring
.Пример:SecurityConfig.java type=java@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/health", "/print-form/**", "/parameters/**", "/dictionary/**", "/user/jwt", "/sup/**", "/masking/**", "/v2/api-docs", "/v3/api-docs", "/v3/api-docs/**", "/configuration/ui", "/swagger-resources/**", "/configuration/security", "/swagger-ui.html", "/swagger-ui/**", "/*.zip", "/webjars/**", "/actuator/**"); }
-
Для демонстрации данных, полученных после аутентификации, добавьте контроллер
UserController
.Чтобы получить данные аутентификации, воспользуйтесь интерфейсомorg.springframework.security.core.Authentication
. Параметры:credentials
— значение JWT-токена;details
— данные из JWT в виде HashMap;principal
— значение поляIssuer
из JWT-токена.
UserController.java type=javapackage com.sbt.demo.ufsrest.controllers; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import ru.sbrf.ufs.platform.jwt.authentication.filter.authorization.efs.UserInfoService; import ru.sbrf.ufs.provider.api.dto.user.UserInfo; import java.util.Map; @Tag(name = "Данные пользователя") @RestController @RequestMapping("user") @RequiredArgsConstructor @CrossOrigin(origins = "*") public class UserController1 { private final UserInfoService userInfoService; @GetMapping("authentication") @PreAuthorize("hasAuthority('SYNT_MS.SMEV.View')") @Operation(summary = "Отображение прав и групп пользователей", security = @SecurityRequirement(name = "bearerAuth")) public Authentication authentication(Authentication authentication) { return authentication; } @Operation(summary = "Получение данных о пользователе ЕСИА", description="Позволяет получить данные о пользователе ЕСИА, которые были получены на этапе аутентификации." + "Состав данных настраивается в IAM."+ "В запросе необходимо передать два заголовка: Authorization с Bearer JWT", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Запрос выполнен успешно", content = @Content(schema = @Schema(implementation = UserInfo.class))), @ApiResponse(responseCode = "403", description = "Некорректное JWT") }) @GetMapping("personal") public Map<String, Object> personal(Authentication authentication) { return userInfoService.getFlatUserInfo(authentication); } }
Настройка аудита
Для библиотеки авторизации и регистрации событий информационной безопасности рекомендуется настроить метамодель аудита. Это позволит видеть события, которые автоматически собирает библиотека.
Чтобы настроить аудит, определите параметры в тегах
audit
и metaModel
.Параметры | Пример заполнения / Тип данных | Описание |
---|---|---|
Тег audit | ||
enabled | boolean | Включение/выключение аудита. По умолчанию false |
url | http://audit_url/ | Хост аудита |
mode | ASYNC , SYNC | Режим отправки запросов в аудит. При режиме ASYNC запросы обрабатываются в разных потоках без необходимости ждать выполнения предыдущих |
Тег metaModel | ||
metamodelVersion | integer | Версия метамодели. Инкрементируйте значение версии при любом изменении модели |
module | string | Имя прикладного приложения |
events | [{...},...] | События, которые нужно аудировать |
Модель данных для аудита регистрируется на старте приложения.
Пример настройки аудита:
application.yml type=yml#Настройка аудита Платформы audit: #Mode of sending messages to audit(default sync). available values [async|sync]. mode: sync| # синхронно или асинхронно отправлять запросы в audit-service(по умолчанию sync). Доступные значения [async|sync] enabled: false # вкл/выкл url: { AUDIT_HOST } metamodel: metaModelVersion: 1 # инкрементировать каждый раз при изменении модели module: { NAME } # имя модуля events: - name: FAILED_LOGIN description: Ошибочная попытка логина success: true mode: reliability params: - name: jwt description: JWT токен - name: reason description: Причина - name: appHost description: Хост, с которого отправили событие в аудит - name: UNAUTHORIZED_ACCESS description: Ошибочная попытка авторизации success: true mode: reliability params: - name: sessionId description: Идентификатор сессии - name: requiredPermission description: Требуемые разрешения - name: api description: Проверямый эндпоинт - name: appHost description: Хост, с которого отправили событие в аудит - name: AUTHORIZED_SUCCESS description: Успешная авторизация success: true mode: reliability params: - name: sessionId description: Идентификатор сессии - name: permission description: Требуемые разрешения - name: api description: Проверямый эндпоинт - name: appHost description: Хост, с которого отправили событие в аудит
События в блоке
events
отправляются в аудит с помощью класса ru.sbrf.ufs.platform.audit.AuditFacade
.Если вам требуется получать права и группы пользователей в приложениях на других языках программирования, или вы не можете использовать Spring Security, воспользуйтесь методом
/authorize
UFS Provider. В ответ на запрос с переданным JWT-токеном метод вернет права и группы пользователя. Подробнее см. в описании API и в разделе «Интеграционные шлюзы».В демопримерах реализованы стандартные сценарии, демонстрирующие работу отдельных сервисов Платформы ГосТех. Отправка тестовых запросов в демопримерах позволит вам ознакомиться с функциями того или иного сервиса. Доступные демопримеры и описания реализованной в них функциональности представлены ниже.
Аутентификация
Аутентификация в прикладных приложениях с проверкой JWT токена и присвоением сессии уникального идентификатора
Создание локального JWT токена
Создание JWT токена с настраиваемым набором данных пользователя для аутентификации в прикладных приложениях
Получение данных в ЕСИА
Просмотр данных о пользователе из ЕСИА, полученных при аутентификации