В моем последнем посте Я представил, как создать пользовательское правило безопасности в Mirconauts , который позволяет защитить конечную точку, требуя определенного разрешения для идентификатора ресурса. В Mettle мы хотели автоматически добавить некоторую документацию в Swagger на основе пользовательской аннотации безопасности, чтобы любой пользователь, использующий документацию API, знал, какие разрешения необходимы. Это хороший пример документации, сгенерированной из кода, чтобы она всегда была правильной и актуальной.
Спецификация Open API позволяет добавлять дополнительную информацию с помощью “Расширений спецификации”. В аннотациях Java они указаны следующим образом:
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; @Operation( extensions = { @Extension(name = "extensionName", properties = { @ExtensionProperty(name = "name", value = "value") }) } )
Однако, чтобы добавить эти аннотации автоматически, мой коллега Нейк и я использовали картограф аннотаций для подключения к процессу компиляции Micronaut. Вот как мы это сделали:
Зависимости
Запустите новый проект gradle и добавьте его в свой build.gradle:
implementation platform("io.micronaut:micronaut-bom:$micronautVersion") implementation "io.micronaut:micronaut-inject" implementation "io.micronaut:micronaut-runtime" implementation("io.swagger.core.v3:swagger-annotations") implementation project(":custom-security-rule-lib")
Это добавит необходимые аннотации Micronaut и Swagger в ваш путь к классам.
Картограф аннотаций
Расширить Типизированный картограф аннотаций <Требуется разрешение>
интерфейс и реализация, такие как:
import custom.security.rule.RequiredPermission; import io.micronaut.core.annotation.AnnotationValue; import io.micronaut.inject.annotation.TypedAnnotationMapper; import io.micronaut.inject.visitor.VisitorContext; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import java.util.Collections; import java.util.List; public class OpenApiAnnotationMapper implements TypedAnnotationMapper{ @Override public Class annotationType() { return RequiredPermission.class; } @Override public List > map(AnnotationValue annotation, VisitorContext visitorContext) { String resourceIdName = annotation.stringValue("resourceIdName").orElse(null); String permission = annotation.stringValue("permission").orElse(null); AnnotationValue extensionProp = AnnotationValue.builder(ExtensionProperty.class) .member("name", "AuthorisationDescription") .member("value", "Your JWT needs to have " + permission + " permissions for " + resourceIdName) .build(); AnnotationValue extension = AnnotationValue.builder(Extension.class) .member("name", "Security") .member("properties", new AnnotationValue[]{extensionProp}) .build(); AnnotationValue operation = AnnotationValue.builder(Operation.class) .member("extensions", new AnnotationValue[]{extension}) .build(); return List.of(operation); } }
Здесь я решил использовать Типизированный картограф аннотаций
и у вас есть jar, который предоставляет аннотацию пользовательского правила безопасности в пути к классу обработчика аннотаций, но также можно использовать NamedAnnotationMapper
. Named AnnotationMapper
позволяет сопоставлять аннотации, не указывая их в пути к классу – это полезно, если вы хотите, чтобы путь к классу процессора аннотаций был небольшим, как это предлагается в документах Micronaut .
Реализация сопоставления – это случай:
- получение информации из пользовательского правила безопасности
- создание свойства расширения
- создание расширения, содержащего список этого свойства расширения
- создание операции, содержащей список этого расширения
- верните эту операцию
Micronaut не удалит аннотацию, которую вы сопоставляете, поэтому ваша конечная точка по-прежнему будет защищена правилом безопасности. Это также не приведет к удалению существующих Операция
аннотации, она объединит новые Операция
аннотация с существующей.
Обеспечение возможности обнаружения картографа
Чтобы сделать картограф доступным для обнаружения с помощью загрузчика служб java, создайте файл в папке ресурсов с именем META-INF/services/io.micronaut.inject.аннотация. AnnotationMapper
и поместите полное имя картографа внутри:
custom.security.rule.openapi.OpenApiAnnotationMapper
Использование вашего картографа в другом проекте
Добавьте jar в качестве обработчика аннотаций, например, в gradle добавьте следующее в свои зависимости:
//to generate the openapi docsc annotationProcessor("io.micronaut.configuration:micronaut-openapi:1.5.1") //This shows using the jar from a multi-module project //if you're uploading this to a maven repo use the artefact coordinates annotationProcessor project(":custom-security-rule-openapi")
Что генерируется
Когда описанный выше класс и дескриптор службы будут добавлены в путь к классу обработчика аннотаций, средство сопоставления аннотаций будет запущено до процессора аннотаций Micronaut openapi. Это означает, что процессор Open API проанализирует сопоставленную аннотацию @Extension
и сгенерирует следующее:
openapi: 3.0.1 info: title: Example API version: v1 paths: /tenant/{tenantId}: get: operationId: index parameters: - name: tenantId in: path required: true schema: type: string responses: default: description: index default response content: application/json: schema: $ref: '#/components/schemas/HttpStatus' x-Security: AuthorisationDescription: Your JWT needs to have READ_ONLY permissions for tenantId
Обратите внимание на ключ x-Security
, который содержит информацию, указанную в нашей аннотации.
Вывод
Процесс компиляции Micronauts действительно мощный и позволяет создавать множество пользовательских функций – это просто царапает поверхность. Другой способ сделать это – использовать Введите элемент Посетитель
, чтобы изменить @Операцию
аннотацию, когда присутствует @Требуемое разрешение
. Я постараюсь опубликовать сообщение в блоге об этом, чтобы следить за этим.
Приведенный выше код, включая модульные тесты, находится в общедоступном репозитории github: https://github.com/PhilHardwick/micronaut-custom-security-rule .
Оригинал: “https://dev.to/philhardwick/using-micronaut-annotation-mapping-to-automatically-add-security-info-to-swagger-docs-3be8”