Menu

Mettre en place une spécification Open Api avec Spring Boot

Installer, configurer créer une spécification Open Api avec exemple

Le code de ce tutoriel est disponible sur GitHub, si vous souhaitez le consulter directement.
https://github.com/Kwaadpepper/Demo-SpringBoot-OpenApi

Spring%20Initailizer.png

Initialiser un projet

Nous utiliserons Spring Web, Spring Security pour la configuration en cas réel et Open Api avec l'interface Swagger intégrée directement qui est optionnelle.
 Nous réaliserons quelques routes d'exemple et ajouterons des annotations.
Vous pouvez utiliser https://start.spring.io/ pour initialiser votre projet, j'utiliserai Java 21 et Spring Boot 3.5.5.

 

 

 

 

Voici ce que vous devriez avoir dans vos dépendances

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.5.5'
	id 'io.spring.dependency-management' version '1.1.7'
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

	implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.11'
	implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.11'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

Notez que j'ai ajouté les dépendances de springdoc pour publier la spécification Open Api ainsi que pour avoir l'interface SwaggerUI qui est cependant optionnelle.

Configurer OpenApi

Vous allez avoir besoin d'un Bean pour la configuration de la spécification.

@Configuration
public class OpenApiConfig {

  @Bean
  OpenAPI openApi() {
    return new OpenAPI()
        .addSecurityItem(new SecurityRequirement().addList("Cookie Authentication"))
        .components(
            new Components().addSecuritySchemes("Cookie Authentication", createApiCookieScheme()))
        .info(
            new Info()
                .title("Demo OpenApi")
                .description("Demo OpenApi using Spring Boot and Spring Security")
                .version("0.0.1")
                .contact(
                    new Contact()
                        .name("Munsch Jeremy")
                        .email("github@jeremydev.ovh")
                        .url("https://jeremydev.ovh")));
  }

  private SecurityScheme createApiCookieScheme() {
    return new SecurityScheme()
        .type(SecurityScheme.Type.APIKEY)
        .in(SecurityScheme.In.COOKIE)
        .name(CookieService.COOKIE_NAME);
  }
}

Et voici un exemple de configuration pour Spring Security :

@Configuration
public class SpringSecurityConfig {

  @Bean
  SecurityFilterChain securityFilterChain(
      HttpSecurity http, StaticCredentialFilter staticCredentialFilter) throws Exception {

    final List<String> routesToIgnore =
        List.of(
            "/api/auth/login",
            "/v3/api-docs/**",
            "/swagger-ui.html",
            "/swagger-ui/**",
            "/actuator/**");

    return http.sessionManagement(
            // No cookie session, just state less API.
            session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        // No CSRF for stateless APIs.
        .csrf(AbstractHttpConfigurer::disable)
        // 401 on unauthenticated requests.
        .exceptionHandling(
            handling ->
                handling.authenticationEntryPoint(
                    new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
        // All requests must be authenticated unless explicitly ignored.
        .authorizeHttpRequests(
            request -> {
              // Allow non protected AuthRequestToUrls are not protected.
              request.requestMatchers(routesToIgnore.toArray(String[]::new)).permitAll();

              // Any other routes are.
              request.anyRequest().fullyAuthenticated();
            })
        // Custom filter to process our static user authentication.
        .addFilterAt(staticCredentialFilter, UsernamePasswordAuthenticationFilter.class)
        .build();
  }
}

Notez que dans le Bean pour Open Api, il est spécifié une authentification par Cookie.
Ainsi, nous disons que les routes sont protégées par défaut, ce qui est le cas dans notre configuration Spring Security.
Cependant, pour définir une route non protégée comme celle de login nous pouvons utiliser les annotations suivantes :

  @io.swagger.v3.oas.annotations.parameters.RequestBody(
      content =
          @Content(
              mediaType = "application/json",
              schema = @Schema(implementation = LoginRequest.class),
              examples = {
                @ExampleObject(
                    name = "Exemple de login",
                    value = "{\"login\": \"user.example\", \"password\": \"Password.1\"}")
              }))
  @ApiResponses(
      value = {
        @ApiResponse(
            responseCode = "200",
            description = "Successfully authenticated",
            headers = {
              @Header(
                  name = "set-cookie",
                  description = "Session cookie HTTP Only",
                  schema = @Schema(type = "string"))
            },
            content = @Content(schema = @Schema(implementation = ResponseDto.class))),
        @ApiResponse(
            responseCode = "401",
            description = "User could not be authenticated",
            content =
                @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = ApiErrorDetails.class)))
      })
  @SecurityRequirements
  @PostMapping(
      value = "/api/auth/login",
      consumes = MediaType.APPLICATION_JSON_VALUE,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<ResponseDto> login(@Valid @RequestBody final LoginRequest request) {
      ....
  }

Notez @SecurityRequirements, cette annotation est définie comme étant vide, ainsi, nous disons que la route n'est pas protégée.
Il faut préciser que pour avoir une spécification assez complète, il faudra ajouter pas mal d'annotations, notamment pour les requêtes et les réponses.

Il peut être intéressant de générer la spécification et de s'y conformer à l'aide d'un client qui sera généré comme HeyApi à l'instar de SOAP. L'autre possibilité de créer directement la spécification et de faire en sorte que le backend y soit conforme peut être plus difficile étant donné qu'il n'existe pas de moyen à ma connaissance de le valider programmatiquement avec une spécification.

Vous pourrez trouver sur ce lien la documentation concernant les annotations. Il existe également une librairie pouvant générer des clients à partir de spécifications.

Accéder à la spécification Open Api

Si vous avez suivi la configuration que je vous ai donnée ou l'exemple du dépôt GitHub.

Vous pourrez accéder à votre spécification à partir de http://localhost:8080/v3/api-docs et l'interface Swagger à partir de cette URL http://localhost:8080/swagger-ui/index.html 

SwaggerUI.png
vendredi 5 septembre 2025