Spring Security 5 za reaktivne aplikacije

1. Uvod

U ovom ćemo članku istražiti nove značajke Spring Security 5 okvira za zaštitu reaktivnih aplikacija. Ovo je izdanje usklađeno s Spring 5 i Spring Boot 2.

U ovom članku nećemo ulaziti u detalje o samim reaktivnim aplikacijama, što je nova značajka okvira Spring 5. Svakako pročitajte članak Uvod u jezgru reaktora za više detalja.

2. Postavljanje Mavena

Koristit ćemo pokretače Spring Boot za pokretanje našeg projekta zajedno sa svim potrebnim ovisnostima.

Osnovna postavka zahtijeva roditeljsku deklaraciju, ovisnosti o pokretaču weba i sigurnosti. Trebat će nam i testni test Spring Security:

 org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE org.springframework.boot spring-boot-starter-webflux org.springframework.boot spring-boot-starter-security org.springframework.security spring-security- test test 

Možemo provjeriti trenutnu verziju sigurnosnog startera Spring Boot u Maven Central.

3. Postavljanje projekta

3.1. Podizanje reaktivne aplikacije

Nećemo koristiti standard @SpringBootApplication konfiguraciju, ali umjesto toga konfigurirajte web poslužitelj zasnovan na Nettyu. Netty je asinkroni NIO-ov okvir koji je dobar temelj za reaktivne primjene.

The @EnableWebFlux napomena omogućuje standardnu ​​konfiguraciju Spring Web Reactive za aplikaciju:

@ComponentScan (basePackages = {"com.baeldung.security"}) @EnableWebFlux javna klasa SpringSecurity5Application {public static void main (String [] args) {try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (Context). NettyContext.class) .onClose (). Block (); }}

Ovdje stvaramo novi kontekst aplikacije i čekamo da se Netty isključi pozivom .onClose (). block () lanac na Nettyjevom kontekstu.

Nakon isključivanja Netty-a, kontekst će se automatski zatvoriti pomoću pokušajte s resursima blok.

Također ćemo trebati stvoriti HTTP poslužitelj zasnovan na Nettyju, obrađivač za HTTP zahtjeve i adapter između poslužitelja i obrađivača:

@Bean public NettyContext nettyContext (ApplicationContext context) {HttpHandler handler = WebHttpHandlerBuilder .applicationContext (context) .build (); ReactorHttpHandlerAdapter adapter = novi ReactorHttpHandlerAdapter (rukovatelj); HttpServer httpServer = HttpServer.create ("localhost", 8080); vrati httpServer.newHandler (adapter) .block (); }

3.2. Proljetna klasa sigurnosne konfiguracije

Za našu osnovnu konfiguraciju Spring Security stvorit ćemo klasu konfiguracije - SecurityConfig.

Da bismo omogućili podršku za WebFlux u Spring Security 5, trebamo samo navesti @EnableWebFluxSecurity napomena:

@EnableWebFluxSecurity javna klasa SecurityConfig {// ...}

Sada možemo iskoristiti nastavu ServerHttpSecurity za izgradnju naše sigurnosne konfiguracije.

Ova klasa nova je značajka Proljeća 5. Slično je HttpSecurity builder, ali omogućen je samo za WebFlux aplikacije.

The ServerHttpSecurity je već unaprijed konfiguriran s nekim zdravim zadanim postavkama, pa bismo mogli u potpunosti preskočiti ovu konfiguraciju. No, za početak ćemo pružiti sljedeću minimalnu konfiguraciju:

@Bean public SecurityWebFilterChain securitygWebFilterChain (ServerHttpSecurity http) {return http.authorizeExchange () .anyExchange (). Authenticated () .and (). Build (); }

Također, trebat će nam usluga s pojedinostima o korisniku. Spring Security pruža nam prikladan lažni graditelj korisnika i implementaciju usluge korisničkih detalja u memoriji:

@Bean public MapReactiveUserDetailsService userDetailsService () {UserDetails user = User .withUsername ("user") .password (passwordEncoder (). Encode ("password")) .roles ("USER") .build (); vratiti novu MapReactiveUserDetailsService (korisnik); }

Budući da smo u reaktivnom zemljištu, usluga s podacima o korisniku također bi trebala biti reaktivna. Ako provjerimo ReactiveUserDetailsService sučelje, vidjet ćemo da je to findByUsername metoda zapravo vraća a Mono izdavač:

javno sučelje ReactiveUserDetailsService {Mono findByUsername (korisničko ime niza); }

Sada možemo pokrenuti našu aplikaciju i promatrati redoviti HTTP osnovni obrazac za provjeru autentičnosti.

4. Stilizirani obrazac za prijavu

Malo, ali zapanjujuće poboljšanje u Spring Security 5 novi je stilski obrazac za prijavu koji koristi Bootstrap 4 CSS okvir. Tablice stilova u obrascu za prijavu povezuju se na CDN, pa ćemo poboljšanje vidjeti tek kad smo povezani s Internetom.

Da bismo koristili novi obrazac za prijavu, dodajmo odgovarajući formLogin () graditeljska metoda za ServerHttpSecurity graditelj:

javni SecurityWebFilterChain securitygWebFilterChain (ServerHttpSecurity http) {return http.authorizeExchange () .anyExchange (). authenticated () .and (). formLogin () .and (). build (); }

Ako sada otvorimo glavnu stranicu aplikacije, vidjet ćemo da izgleda puno bolje od zadanog obrasca na koji smo navikli od prethodnih verzija Spring Securitya:

Imajte na umu da ovo nije obrazac spreman za proizvodnju, ali je dobar bootstrap naše aplikacije.

Ako se sada prijavimo, a zatim idemo na // localhost: 8080 / logout URL, vidjet ćemo obrazac za potvrdu odjave, koji je također oblikovan.

5. Sigurnost reaktivnog kontrolera

Da bismo vidjeli nešto iza obrasca za provjeru autentičnosti, implementiramo jednostavni reaktivni kontroler koji pozdravlja korisnika:

@RestController javna klasa GreetController {@GetMapping ("/") public Mono greet (Mono principal) {return principal .map (Principal :: getName) .map (name -> String.format ("Hello,% s", name) ); }}

Nakon prijave vidjet ćemo pozdrav. Dodajmo još jedan reaktivni rukovatelj kojem bi mogao pristupiti samo administrator:

@GetMapping ("/ admin") javni Mono greetAdmin (Mono principal) {return principal .map (Principal :: getName) .map (name -> String.format ("Admin access:% s", name)); }

Ajmo sada stvoriti drugog korisnika s ulogom UPRAVNIK: u našoj usluzi korisničkih podataka:

UserDetails admin = User.withDefaultPasswordEncoder () .username ("admin") .password ("lozinka") .roles ("ADMIN") .build ();

Sada možemo dodati pravilo podudaranja za admin URL koji zahtijeva da korisnik ima ROLE_ADMIN autoritet.

Imajte na umu da moramo staviti podudaranje prije .anyExchange () lančani poziv. Ovaj se poziv odnosi na sve ostale URL-ove koji još nisu obuhvaćeni drugim podudarnostima:

vrati http.authorizeExchange () .pathMatchers ("/ admin"). hasAuthority ("ROLE_ADMIN") .anyExchange (). authenticated () .and (). formLogin () .and (). build ();

Ako se sada prijavimo s korisnik ili admin, vidjet ćemo da oboje promatraju početni pozdrav, jer smo ga učinili dostupnim za sve ovjerene korisnike.

Ali samo admin korisnik može otići na // localhost: 8080 / admin URL i vidjeti njezin pozdrav.

6. Sigurnost reaktivne metode

Vidjeli smo kako možemo osigurati URL-ove, ali što je s metodama?

Da bismo omogućili sigurnost zasnovanu na metodama za reaktivne metode, trebamo samo dodati @EnableReactiveMethodSecurity napomena za našu SecurityConfig razred:

@EnableWebFluxSecurity @EnableReactiveMethodSecurity javna klasa SecurityConfig {// ...}

Sada izradimo reaktivnu uslugu pozdrava sa sljedećim sadržajem:

@Service javna klasa GreetService {public Mono greet () {return Mono.just ("Hello from service!"); }}

Možemo ga ubrizgati u kontroler, otići na // localhost: 8080 / greetService i vidjeti da li stvarno radi:

@RestController javna klasa GreetController {private GreetService greetService @GetMapping ("/ greetService") public Mono greetService () {return greetService.greet (); } // standardni konstruktori ...}

Ali ako sada dodamo @PreAuthorize napomena o načinu usluge s UPRAVNIK ulogu, tada URL usluge pozdravljanja neće biti dostupan redovnom korisniku:

@Service javna klasa GreetService {@PreAuthorize ("hasRole ('ADMIN')") javni Mono pozdrav () {// ...}

7. Izrugivanje korisnika u testovima

Provjerimo kako je jednostavno testirati našu reaktivnu aplikaciju Spring.

Prvo ćemo stvoriti test s ubrizganim kontekstom aplikacije:

@ContextConfiguration (classes = SpringSecurity5Application.class) javna klasa SecurityTest {@Autowired ApplicationContext context; // ...}

Sada ćemo postaviti jednostavni klijent za reaktivni web test, što je značajka testnog okvira Spring 5:

@Prije javne void setup () {this.rest = WebTestClient .bindToApplicationContext (this.context) .configureClient () .build (); }

To nam omogućuje brzu provjeru preusmjeravanja neovlaštenog korisnika s glavne stranice naše aplikacije na stranicu za prijavu:

@Test public void whenNoCredentials_thenRedirectToLogin () {this.rest.get () .uri ("/") .exchange () .expectStatus (). Is3xxRedirection (); }

Ako sada dodamo @MockWithUser Napomena testnoj metodi, možemo pružiti ovjerenog korisnika za ovu metodu.

Prijava i lozinka ovog korisnika bi bili korisnik i zaporka odnosno uloga je KORISNIK. To se, naravno, sve može konfigurirati pomoću @MockWithUser parametri bilješki.

Sada možemo provjeriti vidi li ovlašteni korisnik pozdrav:

@Test @WithMockUser javna praznina kada jeHasCredentials_thenSeesGreeting () {this.rest.get () .uri ("/") .exchange () .expectStatus (). IsOk () .expectBody (String.class) .isEqualTo ("Zdravo, korisniče "); }

The @WithMockUser napomena je dostupna od Spring Security 4. Međutim, u Spring Security 5 također je ažurirana tako da pokriva reaktivne krajnje točke i metode.

8. Zaključak

U ovom uputstvu otkrili smo nove značajke nadolazećeg izdanja Spring Security 5, posebno u areni reaktivnog programiranja.

Kao i uvijek, izvorni kôd članka dostupan je na GitHubu.


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