Spring Security 5 reaktív alkalmazásokhoz
1. Bemutatkozás
Ebben a cikkben a Spring Security 5 keretrendszer új funkcióit tárjuk fel a reaktív alkalmazások biztonságának biztosítása érdekében. Ez a kiadás összhangban van az 5. tavasszal és a tavaszi csomagtartóval.
Ebben a cikkben nem részletezzük magukat a reaktív alkalmazásokat, amelyek a Spring 5 keretrendszer újdonságai. További részletekért olvassa el az Intro to Reactor Core című cikket.
2. Maven Setup
A Spring Boot indítókat használjuk a projekt indításához a szükséges függőségekkel együtt.
Az alapbeállításhoz szülődeklaráció, webindító és biztonsági indítófüggőség szükséges. Szükségünk lesz a tavaszi biztonsági teszt keretrendszerre is:
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- teszt
Megnézhetjük a Spring Boot security starter aktuális verzióját a Maven Central-nál.
3. Projekt beállítása
3.1. A reaktív alkalmazás indítása
Nem fogjuk használni a szabványt @SpringBootApplication konfigurálásához, hanem állítson be egy Netty-alapú webszervert. A Netty aszinkron NIO alapú keretrendszer, amely jó alapot jelent a reaktív alkalmazásokhoz.
A @EnableWebFlux az annotáció lehetővé teszi a szokásos Spring Web Reactive konfigurációt az alkalmazáshoz:
@ComponentScan (basePackages = {"com.baeldung.security"}) @EnableWebFlux public class SpringSecurity5Application {public static void main (String [] args) {try (AnnotationConfigApplicationContext context = new AnnotationConfigApplecComplex.SplicationContext NettyContext.class) .onClose (). Block (); }}
Itt létrehozunk egy új alkalmazáskörnyezetet, és hívással várjuk, amíg Netty leáll .onClose (). block () lánc a Netty-kontextusban.
Miután Netty leállt, a kontextus automatikusan bezárul a erőforrásokkal próbálkozzon Blokk.
Létre kell hoznunk egy Netty-alapú HTTP szervert, egy kezelőt a HTTP kérésekhez, valamint az adaptert a kiszolgáló és a kezelő között:
@Bean public NettyContext nettyContext (ApplicationContext context) {HttpHandler handler = WebHttpHandlerBuilder .applicationContext (context) .build (); ReactorHttpHandlerAdapter adapter = új ReactorHttpHandlerAdapter (kezelő); HttpServer httpServer = HttpServer.create ("localhost", 8080); return httpServer.newHandler (adapter) .block (); }
3.2. Tavaszi biztonsági konfigurációs osztály
Az alap tavaszi biztonsági konfigurációnkhoz létrehozunk egy konfigurációs osztályt - SecurityConfig.
A WebFlux támogatás engedélyezéséhez a Spring Security 5-ben csak a @EnableWebFluxSecurity kommentár:
@EnableWebFluxSecurity public class SecurityConfig {// ...}
Most kihasználhatjuk az osztály előnyeit ServerHttpSecurity a biztonsági konfigurációnk kiépítéséhez.
Ez az osztály az 5. tavasz újdonsága. Hasonló HttpBiztonság builder, de csak a WebFlux alkalmazásoknál engedélyezett.
A ServerHttpSecurity már előre be van állítva néhány épeszű alapértelmezettel, így ezt a konfigurációt teljesen kihagyhatnánk. De kezdőként a következő minimális konfigurációt fogjuk megadni:
@Bean public SecurityWebFilterChain securitygWebFilterChain (ServerHttpSecurity http) {return http.authorizeExchange () .anyExchange (). Hitelesített () .és (). Build (); }
Szükségünk lesz egy felhasználói adatok szolgáltatására is. A Spring Security kényelmes modellalkotót és a felhasználói részletek szolgáltatás memóriájában történő megvalósítását biztosítja számunkra:
@Bean public MapReactiveUserDetailsService userDetailsService () {UserDetails user = Felhasználó .WithUsername ("felhasználó") .jelszó (passwordEncoder (). Encode ("jelszó")) .roles ("USER") .build (); return new MapReactiveUserDetailsService (felhasználó); }
Mivel reaktív földön vagyunk, a felhasználói adatok szolgáltatásának is reaktívnak kell lennie. Ha megnézzük a ReactiveUserDetailsService felület, meglátjuk, hogy az findByUsername metódus valójában a Monó kiadó:
nyilvános felület ReactiveUserDetailsService {Mono findByUsername (String felhasználónév); }
Most futtathatjuk az alkalmazásunkat, és megfigyelhetünk egy szokásos HTTP alap hitelesítési űrlapot.
4. Stílusú bejelentkezési űrlap
A Spring Security 5 apró, de feltűnő fejlesztése egy új stílusú bejelentkezési űrlap, amely a Bootstrap 4 CSS keretrendszert használja. A bejelentkezési űrlap stíluslapjai a CDN-re mutatnak, így a javulást csak akkor látjuk, ha csatlakozik az internethez.
Az új bejelentkezési űrlap használatához adjuk hozzá a megfelelőt formLogin () építő módszer a ServerHttpSecurity építész:
public SecurityWebFilterChain securitygWebFilterChain (ServerHttpSecurity http) {return http.authorizeExchange () .anyExchange (). hitelesített () .és (). formLogin () .és (). build (); }
Ha most megnyitjuk az alkalmazás főoldalát, látni fogjuk, hogy sokkal jobban néz ki, mint az alapértelmezett űrlap, amelyet a Spring Security korábbi verziói óta megszokhattunk:
Ne feledje, hogy ez nem gyártásra kész forma, de az alkalmazásunk jó bootstrapja.
Ha most bejelentkezünk, majd a // localhost: 8080 / logout URL-re megyünk, akkor megjelenik a kijelentkezés megerősítő űrlapja, amely szintén stílusú.
5. A reaktív vezérlő biztonsága
Ha látni akar valamit a hitelesítési űrlap mögött, valósítsunk meg egy egyszerű reaktív vezérlőt, amely üdvözli a felhasználót:
@RestController nyilvános osztály GreetController {@GetMapping ("/") nyilvános mono üdvözlet (mono fő) {return principál .map (Principal :: getName) .map (név -> String.format ("Hello,% s", név) ); }}
Bejelentkezés után meglátjuk az üdvözletet. Vegyünk fel egy másik reaktív kezelőt, amelyhez csak az admin hozzáférhet:
@GetMapping ("/ admin") nyilvános mono greetAdmin (mono fő) {return principál .map (Principal :: getName) .map (név -> String.format ("Adminisztrátori hozzáférés:% s", név)); }
Most hozzunk létre egy második felhasználót a szerepkörrel ADMIN: a felhasználói adatok szolgáltatásunkban:
UserDetails admin = User.withDefaultPasswordEncoder () .username ("admin") .password ("jelszó") .roles ("ADMIN") .build ();
Most hozzáadhatunk egy illesztő szabályt az adminisztrátori URL-hez, amely megköveteli, hogy a felhasználó rendelkezzen a ROLE_ADMIN hatóság.
Ne feledje, hogy a mérkőzõket a .anyExchange () lánchívás. Ez a felhívás minden más URL-re vonatkozik, amelyekre még nem terjedtek ki más egyeztetők:
return http.authorizeExchange () .pathMatchers ("/ admin"). hasAuthority ("ROLE_ADMIN") .anyExchange (). hitelesítve () .és (). formLogin () .és (). build ();
Ha most bejelentkezünk felhasználó vagy admin, látni fogjuk, hogy mindketten megfigyelik a kezdeti üdvözlést, mivel minden hitelesített felhasználó számára hozzáférhetővé tettük.
De csak a admin a felhasználó meglátogathatja a // localhost: 8080 / admin URL-t, és megnézheti üdvözletét.
6. Reaktív módszer biztonsága
Láttuk, hogyan tudjuk biztosítani az URL-eket, de mi a helyzet a módszerekkel?
A reaktív módszerek módszeralapú biztonságának engedélyezéséhez csak hozzá kell adnunk a @EnableReactiveMethodSecurity annotáció a mi SecurityConfig osztály:
@EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig {// ...}
Hozzunk létre egy reaktív üdvözlő szolgáltatást a következő tartalommal:
@Service nyilvános osztály GreetService {public Mono greet () {return Mono.just ("Hello from service!"); }}
Injektálhatjuk a vezérlőbe, lépjünk a // localhost: 8080 / greetService oldalra, és láthatjuk, hogy valóban működik:
@RestController public class GreetController {private GreetService greetService @GetMapping ("/ greetService") public Mono greetService () {return greetService.greet (); } // szabványos kivitelezők ...}
De ha most hozzáadjuk a @PreAuthorize a szolgáltatás metódusának megjegyzése a ADMIN szerepkör, akkor az üdvözlő szolgáltatás URL-je nem lesz elérhető a rendes felhasználók számára:
@Service public class GreetService {@PreAuthorize ("hasRole ('ADMIN')") public Mono greet () {// ...}
7. Gúnyolódó felhasználók a tesztekben
Nézzük meg, milyen egyszerű tesztelni a reaktív tavaszi alkalmazást.
Először létrehozunk egy tesztet egy injektált alkalmazáskörnyezettel:
@ContextConfiguration (class = SpringSecurity5Application.class) public class SecurityTest {@Autowired ApplicationContext context; // ...}
Most létrehozunk egy egyszerű reaktív webes tesztklienst, amely az 5. tavaszi tesztkeret egyik jellemzője:
@A nyilvános void beállítása előtt () {this.rest = WebTestClient .bindToApplicationContext (this.context) .configureClient () .build (); }
Ez lehetővé teszi számunkra, hogy gyorsan ellenőrizzük, hogy az illetéktelen felhasználót átirányítják-e alkalmazásunk főoldaláról a bejelentkezési oldalra:
@Test public void whenNoCredentials_thenRedirectToLogin () {this.rest.get () .uri ("/") .exchange () .expectStatus (). Is3xxRedirection (); }
Ha most hozzáadjuk a @MockWithUser egy vizsgálati módszer kommentárja, hitelesített felhasználót tudunk biztosítani ehhez a módszerhez.
A felhasználó bejelentkezési neve és jelszava a következő lesz: felhasználó és Jelszó illetve a szerepe az FELHASZNÁLÓ. Ez természetesen mind konfigurálható a @MockWithUser annotációs paraméterek.
Most ellenőrizhetjük, hogy az engedélyezett felhasználó látja-e az üdvözletet:
@Test @WithMockUser public void whenHasCredentials_thenSeesGreeting () {this.rest.get () .uri ("/") .exchange () .expectStatus (). IsOk () .expectBody (String.class) .isEqualTo ("Helló, felhasználó "); }
A @WithMockUser az annotáció a Spring Security 4 óta elérhető. A Spring Security 5-ben azonban frissítették a reaktív végpontokat és módszereket is.
8. Következtetés
Ebben az oktatóanyagban felfedeztük a készülő Spring Security 5 kiadás új funkcióit, különösen a reaktív programozási arénában.
Mint mindig, a cikk forráskódja elérhető a GitHubon.