Рубрики
Без рубрики

Использование сопоставления аннотаций Micronaut для автоматического добавления сведений о безопасности в документы Swagger

В своем последнем посте я рассказал, как создать пользовательское правило безопасности в Mirconauts, которое позволяет вам видеть… С тегами micronaut, swagger, java.

В моем последнем посте Я представил, как создать пользовательское правило безопасности в 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 .

Реализация сопоставления – это случай:

  1. получение информации из пользовательского правила безопасности
  2. создание свойства расширения
  3. создание расширения, содержащего список этого свойства расширения
  4. создание операции, содержащей список этого расширения
  5. верните эту операцию

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”