diff --git a/spring-5/pom.xml b/spring-5/pom.xml
index e9a65232d2..7e30179f07 100644
--- a/spring-5/pom.xml
+++ b/spring-5/pom.xml
@@ -14,7 +14,7 @@
org.springframework.boot
spring-boot-starter-parent
- 2.0.0.M3
+ 2.0.0.M6
@@ -99,6 +99,11 @@
spring-boot-starter-test
test
+
+ org.springframework.security
+ spring-security-test
+ test
+
org.apache.commons
@@ -189,7 +194,7 @@
1.0.0
5.0.0
2.20
- 5.0.0.RELEASE
+ 5.0.1.RELEASE
1.0.1.RELEASE
1.1.3
1.0
diff --git a/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java b/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java
new file mode 100644
index 0000000000..02c91a1879
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java
@@ -0,0 +1,34 @@
+package com.baeldung;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.http.server.reactive.HttpHandler;
+import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
+import org.springframework.web.reactive.config.EnableWebFlux;
+import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
+import reactor.ipc.netty.NettyContext;
+import reactor.ipc.netty.http.server.HttpServer;
+
+@ComponentScan(basePackages = {"com.baeldung.security"})
+@EnableWebFlux
+public class SpringSecurity5Application {
+
+ public static void main(String[] args) {
+ try (AnnotationConfigApplicationContext context =
+ new AnnotationConfigApplicationContext(SpringSecurity5Application.class)) {
+ context.getBean(NettyContext.class).onClose().block();
+ }
+ }
+
+ @Bean
+ public NettyContext nettyContext(ApplicationContext context) {
+ HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context)
+ .build();
+ ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
+ HttpServer httpServer = HttpServer.create("localhost", 8080);
+ return httpServer.newHandler(adapter).block();
+ }
+
+}
diff --git a/spring-5/src/main/java/com/baeldung/security/GreetController.java b/spring-5/src/main/java/com/baeldung/security/GreetController.java
new file mode 100644
index 0000000000..6b69e3bc9b
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/security/GreetController.java
@@ -0,0 +1,37 @@
+package com.baeldung.security;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+
+import java.security.Principal;
+
+@RestController
+public class GreetController {
+
+ private GreetService greetService;
+
+ public GreetController(GreetService greetService) {
+ this.greetService = greetService;
+ }
+
+ @GetMapping("/")
+ public Mono greet(Mono principal) {
+ return principal
+ .map(Principal::getName)
+ .map(name -> String.format("Hello, %s", name));
+ }
+
+ @GetMapping("/admin")
+ public Mono greetAdmin(Mono principal) {
+ return principal
+ .map(Principal::getName)
+ .map(name -> String.format("Admin access: %s", name));
+ }
+
+ @GetMapping("/greetService")
+ public Mono greetService() {
+ return greetService.greet();
+ }
+
+}
diff --git a/spring-5/src/main/java/com/baeldung/security/GreetService.java b/spring-5/src/main/java/com/baeldung/security/GreetService.java
new file mode 100644
index 0000000000..7622b360be
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/security/GreetService.java
@@ -0,0 +1,15 @@
+package com.baeldung.security;
+
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Service
+public class GreetService {
+
+ @PreAuthorize("hasRole('ADMIN')")
+ public Mono greet() {
+ return Mono.just("Hello from service!");
+ }
+
+}
diff --git a/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java b/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java
new file mode 100644
index 0000000000..a9e44a2eee
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java
@@ -0,0 +1,42 @@
+package com.baeldung.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@EnableWebFluxSecurity
+@EnableReactiveMethodSecurity
+public class SecurityConfig {
+
+ @Bean
+ public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
+ return http.authorizeExchange()
+ .pathMatchers("/admin").hasAuthority("ROLE_ADMIN")
+ .anyExchange().authenticated()
+ .and().formLogin()
+ .and().build();
+ }
+
+ @Bean
+ public MapReactiveUserDetailsService userDetailsService() {
+ UserDetails user = User.withDefaultPasswordEncoder()
+ .username("user")
+ .password("password")
+ .roles("USER")
+ .build();
+
+ UserDetails admin = User.withDefaultPasswordEncoder()
+ .username("admin")
+ .password("password")
+ .roles("ADMIN")
+ .build();
+
+ return new MapReactiveUserDetailsService(user, admin);
+ }
+
+}
diff --git a/spring-5/src/main/resources/application.properties b/spring-5/src/main/resources/application.properties
index 886ea1978b..ccec014c2b 100644
--- a/spring-5/src/main/resources/application.properties
+++ b/spring-5/src/main/resources/application.properties
@@ -1,6 +1,3 @@
server.port=8081
-security.user.name=user
-security.user.password=pass
-
logging.level.root=INFO
\ No newline at end of file
diff --git a/spring-5/src/test/java/com/baeldung/security/SecurityTest.java b/spring-5/src/test/java/com/baeldung/security/SecurityTest.java
new file mode 100644
index 0000000000..a1c940a17a
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/security/SecurityTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.security;
+
+import com.baeldung.SpringSecurity5Application;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = SpringSecurity5Application.class)
+public class SecurityTest {
+
+ @Autowired
+ ApplicationContext context;
+
+ private WebTestClient rest;
+
+ @Before
+ public void setup() {
+ this.rest = WebTestClient
+ .bindToApplicationContext(this.context)
+ .configureClient()
+ .build();
+ }
+
+ @Test
+ public void whenNoCredentials_thenRedirectToLogin() {
+ this.rest.get()
+ .uri("/")
+ .exchange()
+ .expectStatus().is3xxRedirection();
+ }
+
+ @Test
+ @WithMockUser
+ public void whenHasCredentials_thenSeesGreeting() {
+ this.rest.get()
+ .uri("/")
+ .exchange()
+ .expectStatus().isOk()
+ .expectBody(String.class).isEqualTo("Hello, user");
+ }
+}
diff --git a/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java b/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java
index b05f903b4b..43114b5b50 100644
--- a/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java
+++ b/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java
@@ -53,7 +53,7 @@ public class WebTestClientTest {
.uri("/resource")
.exchange()
.expectStatus()
- .is4xxClientError()
+ .is3xxRedirection()
.expectBody();
}