Sette opp Swagger 2 med en Spring REST API

Sikkerhetstopp

Jeg kunngjorde nettopp det nye Learn Spring Security-kurset, inkludert hele materialet med fokus på den nye OAuth2-stakken i Spring Security 5:

>> KONTROLLER KURSET REST Topp

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Oversikt

I dag skiller front-end og back-end komponenter ofte en webapplikasjon. Vanligvis eksponerer vi APIer som en back-end-komponent for front-end-komponenten eller tredjeparts appintegrasjoner.

I et slikt scenario er det viktig å ha riktige spesifikasjoner for back-end API-ene. Samtidig skal API-dokumentasjonen være informativ, lesbar og enkel å følge.

Videre bør referansedokumentasjon samtidig beskrive alle endringer i API. Å utføre dette manuelt er en kjedelig øvelse, så automatisering av prosessen var uunngåelig.

I denne opplæringen vil vi se på Swagger 2 for en Spring REST-nettjeneste, ved hjelp av Springfox-implementeringen av Swagger 2-spesifikasjonen.

Hvis du ikke er kjent med Swagger, kan du besøke nettsiden for å lære mer før du fortsetter med denne opplæringen.

2. Målprosjekt

Opprettelsen av REST-tjenesten vi vil bruke ligger ikke innenfor rammen av denne artikkelen. Hvis du allerede har et passende prosjekt, bruk det. Hvis ikke, er disse lenkene et godt sted å starte:

  • Bygg en REST API med Spring 4 og Java Config artikkel
  • Bygg en RESTful Web Service

3. Legge til Maven-avhengighet

Som nevnt ovenfor vil vi bruke Springfox-implementeringen av Swagger-spesifikasjonen. Den siste versjonen finner du på Maven Central.

For å legge det til i Maven-prosjektet vårt, trenger vi en avhengighet i pom.xml fil:

 io.springfox springfox-swagger2 2.9.2 

3.1. Avhengighet av vårstøvler

For Spring Boot-baserte prosjekter, det er nok å legge til en singel springfox-boot-starter avhengighet:

 io.springfox springfox-boot-starter 3.0.0 

4. Integrering av Swagger 2 i prosjektet

4.1. Java-konfigurasjon

Konfigurasjonen av Swagger hovedsakelig rundt Docket bønne:

@Configuration public class SpringFoxConfig {@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.any ()) .paths (PathSelectors.any ()) .build (); }}

Etter å ha definert Docket bønne, dens å velge() metoden returnerer en forekomst av ApiSelectorBuilder, som gir en måte å kontrollere endepunktene eksponert av Swagger.

Vi kan konfigurere predikater for valg RequestHandlers ved hjelp av RequestHandlerSelectors og PathSelectors. Ved hjelp av noen() for begge vil gjøre dokumentasjon for hele API-en vår tilgjengelig gjennom Swagger.

4.2. Konfigurasjon uten fjærstøvel

I vanlige vårprosjekter må vi aktivere Swagger 2 eksplisitt. Å gjøre slik, vi må bruke @ EnableSwagger2WebMvc på vår konfigurasjonsklasse:

@Configuration @ EnableSwagger2WebMvc offentlig klasse SpringFoxConfig {}

I tillegg, uten Spring Boot, har vi ikke luksusen med automatisk konfigurering av ressurshåndtererne.

Swagger UI legger til et sett med ressurser som vi må konfigurere som en del av en klasse som strekker seg WebMvcConfigurerAdapter og er kommentert med @EnableWebMvc:

@Override public void addResourceHandlers (ResourceHandlerRegistry registry) {registry.addResourceHandler ("swagger-ui.html") .addResourceLocations ("classpath: / META-INF / resources /"); registry.addResourceHandler ("/ webjars / **") .addResourceLocations ("classpath: / META-INF / resources / webjars /"); }

4.3. Bekreftelse

For å bekrefte at Springfox fungerer, kan vi gå til denne URL-en i nettleseren vår:

// localhost: 8080 / spring-security-rest / api / v2 / api-docs

Resultatet er et JSON-svar med et stort antall nøkkelverdipar, som ikke er veldig menneskelig lesbart. Heldigvis gir Swagger det Swagger UI for dette formålet.

5. Swagger UI

Swagger UI er en innebygd løsning som gjør brukerinteraksjon med den Swagger-genererte API-dokumentasjonen mye enklere.

5.1. Aktiverer Springfoxs Swagger UI

For å bruke Swagger UI, må vi legge til en ekstra Maven-avhengighet:

 io.springfox springfox-swagger-ui 2.9.2 

Nå kan vi teste det i nettleseren vår ved å gå til:

// localhost: 8080 / your-app-root / swagger-ui /

I vårt tilfelle vil den nøyaktige nettadressen for øvrig være:

// localhost: 8080 / spring-security-rest / api / swagger-ui /

Resultatet skal se ut slik:

5.2. Utforske Swagger-dokumentasjon

Innenfor Swagers svar er et liste over alle kontrollere definert i søknaden vår. Ved å klikke på en av dem vises de gyldige HTTP-metodene (SLETT, , HODE, ALTERNATIVER, LAPP, POST, SETTE).

Å utvide hver metode gir ytterligere nyttige data, for eksempel svarstatus, innholdstype og en liste over parametere. Det er også mulig å prøve hver metode ved hjelp av brukergrensesnittet.

Swagers evne til å bli synkronisert med kodebasen vår er avgjørende. For å demonstrere dette kan vi legge til en ny kontroller i applikasjonen vår:

@RestController offentlig klasse CustomController {@RequestMapping (verdi = "/ tilpasset", metode = RequestMethod.POST) offentlig streng tilpasset () {return "tilpasset"; }}

Nå hvis vi oppdaterer Swagger-dokumentasjonen, ser vi det tilpasset kontroller i listen over kontrollere. Som vi vet er det bare en metode (POST) vist i Swaggers svar.

6. Vårdata REST

Springfox gir støtte for Spring Data REST gjennom springfox-data-rest bibliotek.

Spring Boot tar seg av den automatiske konfigurasjonen hvis den oppdager spring-boot-starter-data-rest på klassestien.

La oss nå opprette en enhet som heter Bruker:

@Entity offentlig klasse bruker {@Id privat Lang id; privat streng fornavn; privat alder; privat streng e-post; // getters og setters}

Så lager vi UserRepository for å legge til CRUD-operasjoner på Bruker enhet:

@Repository offentlig grensesnitt UserRepository utvider CrudRepository {}

Sist importerer vi SpringDataRestConfiguration klasse til SpringFoxConfig klasse:

@ EnableSwagger2WebMvc @Import (SpringDataRestConfiguration.class) offentlig klasse SpringFoxConfig {// ...}

Merk: Vi har brukt @ EnableSwagger2WebMvc kommentar for å aktivere Swagger, da den har erstattet @ EnableSwagger2 kommentar i versjon 3 av bibliotekene.

La oss starte applikasjonen på nytt for å generere spesifikasjonene for Spring Data REST APIer:

Vi kan se at Springfox har generert spesifikasjonene for Bruker enhet med HTTP-metoder som , POST, PUT, PATCH, og SLETT.

7. Bønnevalideringer

Springfox støtter også kommentarene til validering av bønner gjennom springfox-bean-validators bibliotek.

Først legger vi til Maven-avhengigheten til vår pom.xml:

 io.springfox springfox-bean-validators 2.9.2 

En gang til, Hvis vi bruker Spring Boot, trenger vi ikke å oppgi den ovennevnte avhengigheten eksplisitt.

La oss deretter legge til noen valideringsanmerkninger som @Ikke null og @Min til Bruker enhet:

@Entity public class User {// ... @NotNull (message = "Fornavn kan ikke være null") privat streng fornavn; @Min (verdi = 15, melding = "Alder skal ikke være mindre enn 15") @Max (verdi = 65, melding = "Alder skal ikke være større enn 65") privat int alder; }

Til slutt importerer vi BeanValidatorPluginsConfiguration klasse til SpringFoxConfig klasse:

@ EnableSwagger2 @Import (BeanValidatorPluginsConfiguration.class) offentlig klasse SpringFoxConfig {// ...}

La oss ta en titt på endringene i API-spesifikasjonene:

Her kan vi observere at Bruker modellen har * påkrevdfornavn. Også, den minimum og maksimum verdier er definert for alder.

8. Plugin

For å legge til spesifikke funksjoner i API-spesifikasjonene, kan vi opprette et Springfox-plugin. Et plugin kan tilby forskjellige funksjoner, fra å berike modellene og egenskapene til de tilpassede API-oppføringene og standardinnstillingene.

Springfox støtter opprettelsen av plugin gjennom sin spi-modul. Spi-modulen gir noen få grensesnitt som ModelBuilderPlugin, ModelPropertyBuilderPlugin, og ApiListingBuilderPlugin som fungerer som en utvidbarhetskrok for å implementere et tilpasset plugin.

For å demonstrere mulighetene, la oss lage et plugin for å berike e-post eiendommen til Bruker modell. Vi bruker ModelPropertyBuilderPlugin grensesnitt og angi verdiene til mønster og eksempel.

La oss først lage EmailAnnotationPlugin klasse og overstyre støtter metode for å tillate enhver dokumentasjonstype, for eksempel Swagger 1.2 og Swagger 2:

@Component @Order (Validators.BEAN_VALIDATOR_PLUGIN_ORDER) public class EmailAnnotationPlugin implementerer ModelPropertyBuilderPlugin {@Override public boolean supports (DocumentationType delimiter) {return true; }}

Så overstyrer vi søke om metoden for ModelPropertyBuilderPlugin for å stille inn verdiene til bygningsegenskapene:

@Override public void apply (ModelPropertyContext context) {Valgfri e-post = annotationFromBean (kontekst, Email.class); if (email.isPresent ()) {context.getSpecificationBuilder (). facetBuilder (StringElementFacetBuilder.class) .pattern (email.get (). regexp ()); context.getSpecificationBuilder (). eksempel ("[e-postbeskyttet]"); }}

Så API-spesifikasjonene vil vise mønster og eksempel verdiene til eiendommen merket med @Email kommentar.

Deretter legger vi til @Email kommentar til Bruker enhet:

@Entity public class User {// ... @Email (regexp = ". * @. * \ .. *", message = "E-postadresse skal være gyldig") privat streng-e-post; }

Til slutt aktiverer vi EmailAnnotationPlugin i SpringFoxConfig klasse ved å registrere seg som en bønne:

@Import ({BeanValidatorPluginsConfiguration.class}) offentlig klasse SpringFoxConfig {// ... @Bean offentlig EmailAnnotationPlugin emailPlugin () {return new EmailAnnotationPlugin (); }}

La oss sjekke ut EmailAnnotationPlugin i aksjon:

Vi kan se verdien av mønster er den samme regexen (. * @. * \ .. *) fra e-post eiendommen til Bruker enhet.

Tilsvarende verdien av eksempel ([email protected]) er den samme, som definert i søke om metoden for EmailAnnotationPlugin.

9. Avansert konfigurasjon

De Docket bean av applikasjonen vår kan konfigureres for å gi oss mer kontroll over prosessen for generering av API-dokumentasjon.

9.1. Filtrering av API for svar fra Swagger

Det er ikke alltid ønskelig å eksponere dokumentasjonen for hele API. Vi kan begrense Swaggers respons ved å sende parametere til apis () og stier () metoder for Docket klasse.

Som sett ovenfor, RequestHandlerSelectors tillater bruk av noen eller ingen predikater, men kan også brukes til å filtrere API i henhold til basispakken, klassekommentar og metodekommentarer.

PathSelectors gir ytterligere filtrering med predikater, som skanner forespørselsbanene til applikasjonen vår. Vi kan bruke noen(), ingen(), regex (), eller maur().

I eksemplet nedenfor vil vi instruere Swagger om å bare inkludere kontrollere fra en bestemt pakke, med spesifikke baner, ved hjelp av maur() predikat:

@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.basePackage ("com.baeldung.web.controller")) .paths (PathSelectors.ant ("/ foos / * ")) .bygge(); }

9.2. Tilpasset informasjon

Swagger gir også noen standardverdier i sitt svar, som vi kan tilpasse, for eksempel “Api Documentation”, “Created by Contact Email” og “Apache 2.0”.

For å endre disse verdiene kan vi bruke apiInfo (ApiInfo apiInfo) metoden - ApiInfo klasse som inneholder tilpasset informasjon om API:

@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.basePackage ("com.example.controller")) .paths (PathSelectors.ant ("/ foos / *") ) .build () .apiInfo (apiInfo ()); } private ApiInfo apiInfo () {returner nye ApiInfo ("Min REST API", "Noe tilpasset beskrivelse av API.", "API TOS", "Servicevilkår", ny kontakt ("John Doe", "www.eksempel). com "," [email protected] ")," License of API "," API License URL ", Collections.emptyList ()); }

9.3. Tilpassede metoder Svarmeldinger

Swagger tillater globalt overordnede svarmeldinger av HTTP-metoder gjennom Docket’S globalResponseMessage ()metode.

Først må vi instruere Swagger om ikke å bruke standard svarmeldinger. Anta at vi vil overstyre 500 og 403 svarmeldinger for alle metoder.

For å oppnå dette, må noen kode legges til i DocketInitialiseringsblokk (original kode er ekskludert for klarhetens skyld):

.useDefaultResponseMessages (false) .globalResponseMessage (RequestMethod.GET, newArrayList (new ResponseMessageBuilder (). code (500) .message ("500 message") .responseModel (new ModelRef ("Error")) .build (), new ResponseMessageBuilder ) .code (403) .message ("Forbidden!") .build ()));

10. Bytt UI med en OAuth-sikret API

Swagger UI gir en rekke veldig nyttige funksjoner som vi har dekket godt så langt her. Men vi kan egentlig ikke bruke de fleste av disse hvis API-en vår er sikret og ikke tilgjengelig.

La oss se hvordan vi kan la Swagger få tilgang til et OAuth-sikret API ved hjelp av godkjenningskode-tilskuddstypen i dette eksemplet.

Vi konfigurerer Swagger for å få tilgang til vårt sikrede API ved hjelp av SecurityScheme og Sikkerhetskontekst Brukerstøtte:

@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.any ()) .paths (PathSelectors.any ()) .build () .securitySchemes (Arrays.asList (securityScheme) ())) .securityContexts (Arrays.asList (securityContext ())); }

10.1. Sikkerhetskonfigurasjonen

Vi definerer en Sikkerhetskonfigurasjon bønne i vår Swagger-konfigurasjon og angi noen standardinnstillinger:

@Bean public SecurityConfiguration security () {return SecurityConfigurationBuilder.builder () .clientId (CLIENT_ID) .clientSecret (CLIENT_SECRET) .scopeSeparator ("") .useBasicAuthenticationWithAccessCodeGrant (true) .build (); }

10.2. SecurityScheme

Deretter vil vi definere vår SecurityScheme; dette brukes til å beskrive hvordan API-en vår er sikret (Basic Authentication, OAuth2,…).

I vårt tilfelle her vil vi definere en OAuth-ordning som brukes til å sikre ressursserveren vår:

private SecurityScheme securityScheme () {GrantType grantType = new AuthorizationCodeGrantBuilder () .tokenEndpoint (new TokenEndpoint (AUTH_SERVER + "/ token", "oauthtoken")) .tokenRequestEndpoint (new TokenRequestEndpoint (AUTH_SERVER + "/_ENTER)"). bygge(); SecurityScheme oauth = new OAuthBuilder (). Name ("spring_oauth") .grantTypes (Arrays.asList (grantType)) .scopes (Arrays.asList (scopes ())) .build (); returner oauth; }

Merk at vi brukte tildelingstypen Autorisasjonskode, som vi trenger å oppgi et token-endepunkt og autorisasjons-URL til OAuth2-autorisasjonsserveren vår.

Og her er omfanget vi trenger å ha definert:

private AuthorizationScope [] scopes () {AuthorizationScope [] scopes = {new AuthorizationScope ("read", "for read operations"), new AuthorizationScope ("skriv", "for skrivoperasjoner"), new AuthorizationScope ("foo", " Access foo API ")}; returomfang; }

Disse synkroniseres med omfangene vi faktisk har definert i applikasjonen vår, for / foos API.

10.3. SecurityContext

Til slutt må vi definere en SecurityContext for vårt eksempel API:

private SecurityContext securityContext () {return SecurityContext.builder () .securityReferences (Arrays.asList (new SecurityReference ("spring_oauth", scopes ()))) .forPaths (PathSelectors.regex ("/ foos. *")) .build (build) ); }

Legg merke til hvordan navnet vi brukte her i referansen - spring_oauth - synkroniseres med navnet vi brukte tidligere i SecurityScheme.

10.4. Test

Nå som vi har alt klar og klar til å gå, la oss ta en titt på Swagger UI og prøve å få tilgang til Foo API.

Vi har tilgang til Swagger UI lokalt:

//localhost:8082/spring-security-oauth-resource/swagger-ui.html

Som vi kan se, eksisterer det nå en ny autorisasjonsknapp på grunn av våre sikkerhetskonfigurasjoner:

Når vi klikker på Autoriser-knappen, kan vi se følgende forgrunnsvindu for å autorisere Swagger-brukergrensesnittet vårt til å få tilgang til det sikrede API: et:

Noter det:

  • Vi kan allerede se CLIENT_ID og CLIENT_SECRET, ettersom vi har forhåndskonfigurert dem tidligere (men vi kan fortsatt endre dem).
  • Vi kan nå velge omfanget vi trenger.

Slik merkes det sikrede API:

Og nå, endelig, kan vi slå API-en vår!

Naturligvis sier det nesten seg selv at vi må være forsiktige med hvordan vi eksponerer Swagger UI eksternt, nå som denne sikkerhetskonfigurasjonen er aktiv.

11. Konklusjon

I denne artikkelen setter vi opp Swagger 2 for å generere dokumentasjon for en Spring REST API. Vi har også utforsket måter å visualisere og tilpasse Swaggers produksjon. Og til slutt så vi på en enkel OAuth-konfigurasjon for Swagger.

De full gjennomføring av denne veiledningen finner du i GitHub-prosjektet. For å se oppsettet i et Boot-prosjekt, sjekk ut denne GitHub-modulen.

For OAuth-delen er koden tilgjengelig i vårt vår-sikkerhet-oauth-depot.

Og hvis du er student på REST With Spring, gå til leksjon 1 fra modul 7 for et dypdykk i å sette opp Swagger med Spring and Spring Boot.

Sikkerhetsbunn

Jeg kunngjorde nettopp det nye Learn Spring Security-kurset, inkludert hele materialet med fokus på den nye OAuth2-stakken i Spring Security 5:

>> KONTROLLER KURSET HVILLE bunnen

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

$config[zx-auto] not found$config[zx-overlay] not found