From 01dc0da86cf26643bf0ec34c0fbad788c6dcf7c5 Mon Sep 17 00:00:00 2001 From: maryarm Date: Sat, 30 Nov 2019 21:09:33 +0200 Subject: [PATCH 1/3] BAEL-3338: A Guide to AuthenticationManagerResolver in Spring Security --- spring-5-reactive-security/pom.xml | 1 + .../authresolver/AuthResolverApplication.java | 15 +++ .../authresolver/AuthResolverController.java | 25 +++++ .../AuthResolverSecurityConfig.java | 86 +++++++++++++++++ .../AuthResolverIntegrationTest.java | 62 +++++++++++++ spring-5-security/pom.xml | 5 +- .../authresolver/AuthResolverApplication.java | 11 +++ .../authresolver/AuthResolverController.java | 18 ++++ .../AuthResolverWebSecurityConfigurer.java | 92 +++++++++++++++++++ .../AuthResolverIntegrationTest.java | 80 ++++++++++++++++ 10 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverApplication.java create mode 100644 spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java create mode 100644 spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java create mode 100644 spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java create mode 100644 spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java create mode 100644 spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java create mode 100644 spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java create mode 100644 spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java diff --git a/spring-5-reactive-security/pom.xml b/spring-5-reactive-security/pom.xml index 72a73a86ce..1a7dba2b9e 100644 --- a/spring-5-reactive-security/pom.xml +++ b/spring-5-reactive-security/pom.xml @@ -129,6 +129,7 @@ 1.0 4.1 3.1.6.RELEASE + 2.2.1.RELEASE diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverApplication.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverApplication.java new file mode 100644 index 0000000000..bad5768c20 --- /dev/null +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.reactive.authresolver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.reactive.config.EnableWebFlux; + +@EnableWebFlux +@SpringBootApplication +public class AuthResolverApplication { + + public static void main(String[] args) { + SpringApplication.run(AuthResolverApplication.class, args); + } + +} diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java new file mode 100644 index 0000000000..fdce66380b --- /dev/null +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java @@ -0,0 +1,25 @@ +package com.baeldung.reactive.authresolver; + +import java.security.Principal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class AuthResolverController { + + @GetMapping("/customer/welcome") + public Mono sayWelcomeToCustomer(Mono principal) { + return principal + .map(Principal::getName) + .map(name -> String.format("Welcome to our site, %s!", name)); + } + + @GetMapping("/employee/welcome") + public Mono sayWelcomeToEmployee(Mono principal) { + return principal + .map(Principal::getName) + .map(name -> String.format("Welcome to our company, %s!", name)); + } + +} diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java new file mode 100644 index 0000000000..65ee47ecc4 --- /dev/null +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java @@ -0,0 +1,86 @@ +package com.baeldung.reactive.authresolver; + +import java.util.Collections; +import org.springframework.context.annotation.Bean; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +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.SecurityWebFiltersOrder; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.authentication.AuthenticationWebFilter; +import reactor.core.publisher.Mono; + +@EnableWebFluxSecurity +@EnableReactiveMethodSecurity +public class AuthResolverSecurityConfig { + + @Bean + public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + return http + .authorizeExchange() + .pathMatchers("/**") + .authenticated() + .and() + .httpBasic() + .disable() + .addFilterAfter(authenticationWebFilter(), SecurityWebFiltersOrder.REACTOR_CONTEXT) + .build(); + } + + public AuthenticationWebFilter authenticationWebFilter() { + AuthenticationWebFilter filter = new AuthenticationWebFilter(authenticationManagerResolver()); + return filter; + } + + public ReactiveAuthenticationManagerResolver authenticationManagerResolver() { + return request -> { + if (request + .getPath() + .subPath(0) + .value() + .startsWith("/employee")) return Mono.just(employeesAuthenticationManager()); + return Mono.just(customersAuthenticationManager()); + }; + } + + public ReactiveAuthenticationManager customersAuthenticationManager() { + return authentication -> customer(authentication) + .switchIfEmpty(Mono.error(new UsernameNotFoundException(authentication + .getPrincipal() + .toString()))) + .map(b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))); + } + + public ReactiveAuthenticationManager employeesAuthenticationManager() { + return authentication -> employee(authentication) + .switchIfEmpty(Mono.error(new UsernameNotFoundException(authentication + .getPrincipal() + .toString()))) + .map(b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))); + } + + public Mono customer(Authentication authentication) { + return Mono.justOrEmpty(authentication + .getPrincipal() + .toString() + .startsWith("customer") ? authentication + .getPrincipal() + .toString() : null); + } + + public Mono employee(Authentication authentication) { + return Mono.justOrEmpty(authentication + .getPrincipal() + .toString() + .startsWith("employee") ? authentication + .getPrincipal() + .toString() : null); + } +} diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java b/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java new file mode 100644 index 0000000000..21c25a6111 --- /dev/null +++ b/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java @@ -0,0 +1,62 @@ +package com.baeldung.reactive.authresolver; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.Base64Utils; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class AuthResolverIntegrationTest { + @Autowired private WebTestClient testClient; + + @Test + public void givenCustomerCredential_whenWelcomeCustomer_thenExpectOk() { + testClient + .get() + .uri("/customer/welcome") + .header("Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes())) + .exchange() + .expectStatus() + .isOk(); + } + + @Test + public void givenEmployeeCredential_whenWelcomeCustomer_thenExpect401Status() { + testClient + .get() + .uri("/customer/welcome") + .header("Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes())) + .exchange() + .expectStatus() + .isUnauthorized(); + } + + @Test + public void givenEmployeeCredential_whenWelcomeEmployee_thenExpectOk() { + testClient + .get() + .uri("/employee/welcome") + .header("Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes())) + .exchange() + .expectStatus() + .isOk(); + } + + @Test + public void givenCustomerCredential_whenWelcomeEmployee_thenExpect401Status() { + testClient + .get() + .uri("/employee/welcome") + .header("Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes())) + .exchange() + .expectStatus() + .isUnauthorized(); + } +} diff --git a/spring-5-security/pom.xml b/spring-5-security/pom.xml index 413337633f..943bfbdc1f 100644 --- a/spring-5-security/pom.xml +++ b/spring-5-security/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung spring-5-security @@ -60,5 +60,8 @@ + + 2.2.1.RELEASE + diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java new file mode 100644 index 0000000000..96ee674b15 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.authresolver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AuthResolverApplication { + public static void main(String[] args) { + SpringApplication.run(AuthResolverApplication.class, args); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java new file mode 100644 index 0000000000..7dc6900b5a --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java @@ -0,0 +1,18 @@ +package com.baeldung.authresolver; + +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class AuthResolverController { + @GetMapping("/customer/welcome") + public String sayWelcomeToCustomer(Authentication authentication) { + return String.format("Welcome to our site, %s!", authentication.getPrincipal()); + } + + @GetMapping("/employee/welcome") + public String sayWelcomeToEmployee(Authentication authentication) { + return String.format("Welcome to our company, %s!", authentication.getPrincipal()); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java new file mode 100644 index 0000000000..6f8931eb7a --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java @@ -0,0 +1,92 @@ +package com.baeldung.authresolver; + +import java.util.Arrays; +import javax.servlet.http.HttpServletRequest; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationManagerResolver; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.security.web.authentication.AuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationConverter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +@Configuration +public class AuthResolverWebSecurityConfigurer extends WebSecurityConfigurerAdapter { + + public AuthenticationConverter authenticationConverter() { + return new BasicAuthenticationConverter(); + } + + public AuthenticationManagerResolver authenticationManagerResolver() { + return request -> { + if (request + .getPathInfo() + .startsWith("/employee")) return employeesAuthenticationManager(); + return customersAuthenticationManager(); + }; + } + + public AuthenticationManager customersAuthenticationManager() { + return authentication -> { + if (isCustomer(authentication)) { + return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + } + throw new UsernameNotFoundException(authentication + .getPrincipal() + .toString()); + }; + } + + public boolean isCustomer(Authentication authentication) { + return (authentication + .getPrincipal() + .toString() + .startsWith("customer")); + } + + public boolean isEmployee(Authentication authentication) { + return (authentication + .getPrincipal() + .toString() + .startsWith("employee")); + } + + public AuthenticationFilter authenticationFilter(AuthenticationManagerResolver resolver, AuthenticationConverter converter) { + AuthenticationFilter ret = new AuthenticationFilter(resolver, converter); + ret.setSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> { + }); + return ret; + } + + public AuthenticationManager employeesAuthenticationManager() { + return authentication -> { + if (isEmployee(authentication)) { + return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + } + throw new UsernameNotFoundException(authentication + .getPrincipal() + .toString()); + }; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .addFilterBefore( + authenticationFilter( + authenticationManagerResolver(), authenticationConverter()), + BasicAuthenticationFilter.class); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + super.configure(auth); + } +} diff --git a/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java b/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java new file mode 100644 index 0000000000..0b0289e9e5 --- /dev/null +++ b/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java @@ -0,0 +1,80 @@ +package com.baeldung.authresolver; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.Base64Utils; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class AuthResolverIntegrationTest { + + @Autowired private FilterChainProxy springSecurityFilterChain; + + @Autowired private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders + .webAppContextSetup(wac) + .apply(springSecurity(springSecurityFilterChain)) + .build(); + } + + @Test + public void givenCustomerCredential_whenWelcomeCustomer_thenExpectOk() throws Exception { + this.mockMvc + .perform(get("/customer/welcome") + .header( + "Authorization", String.format("Basic %s", Base64Utils.encodeToString("customer1:pass1".getBytes())) + ) + ) + .andExpect(status().is2xxSuccessful()); + } + + @Test + public void givenEmployeeCredential_whenWelcomeCustomer_thenExpect401Status() throws Exception { + this.mockMvc + .perform(get("/customer/welcome") + .header( + "Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes())) + ) + .andExpect(status().isUnauthorized()); + } + + @Test + public void givenEmployeeCredential_whenWelcomeEmployee_thenExpectOk() throws Exception { + this.mockMvc + .perform(get("/employee/welcome") + .header( + "Authorization", "Basic " + Base64Utils.encodeToString("employee1:pass1".getBytes())) + ) + .andExpect(status().is2xxSuccessful()); + } + + @Test + public void givenCustomerCredential_whenWelcomeEmployee_thenExpect401Status() throws Exception { + this.mockMvc + .perform(get("/employee/welcome") + .header( + "Authorization", "Basic " + Base64Utils.encodeToString("customer1:pass1".getBytes())) + ) + .andExpect(status().isUnauthorized()); + } +} From 5d95761a997bff6cad9570795426e564cb2e4f70 Mon Sep 17 00:00:00 2001 From: maryarm Date: Mon, 2 Dec 2019 16:33:37 +0200 Subject: [PATCH 2/3] BAEL-3338: A Guide to AuthenticationManagerResolver in Spring Security Fix indentation problems in code, do some renaming to sync article with code --- .../authresolver/AuthResolverController.java | 8 +-- ...nfig.java => CustomWebSecurityConfig.java} | 23 ++++++--- .../AuthResolverIntegrationTest.java | 3 +- ....java => CustomWebSecurityConfigurer.java} | 51 ++++++++++--------- .../AuthResolverIntegrationTest.java | 6 ++- 5 files changed, 53 insertions(+), 38 deletions(-) rename spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/{AuthResolverSecurityConfig.java => CustomWebSecurityConfig.java} (82%) rename spring-5-security/src/main/java/com/baeldung/authresolver/{AuthResolverWebSecurityConfigurer.java => CustomWebSecurityConfigurer.java} (57%) diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java index fdce66380b..1d70ded5e4 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverController.java @@ -11,15 +11,15 @@ public class AuthResolverController { @GetMapping("/customer/welcome") public Mono sayWelcomeToCustomer(Mono principal) { return principal - .map(Principal::getName) - .map(name -> String.format("Welcome to our site, %s!", name)); + .map(Principal::getName) + .map(name -> String.format("Welcome to our site, %s!", name)); } @GetMapping("/employee/welcome") public Mono sayWelcomeToEmployee(Mono principal) { return principal - .map(Principal::getName) - .map(name -> String.format("Welcome to our company, %s!", name)); + .map(Principal::getName) + .map(name -> String.format("Welcome to our company, %s!", name)); } } diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java similarity index 82% rename from spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java rename to spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java index 65ee47ecc4..cd5a0af5a2 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/AuthResolverSecurityConfig.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java @@ -19,7 +19,7 @@ import reactor.core.publisher.Mono; @EnableWebFluxSecurity @EnableReactiveMethodSecurity -public class AuthResolverSecurityConfig { +public class CustomWebSecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { @@ -35,17 +35,17 @@ public class AuthResolverSecurityConfig { } public AuthenticationWebFilter authenticationWebFilter() { - AuthenticationWebFilter filter = new AuthenticationWebFilter(authenticationManagerResolver()); - return filter; + return new AuthenticationWebFilter(resolver()); } - public ReactiveAuthenticationManagerResolver authenticationManagerResolver() { + public ReactiveAuthenticationManagerResolver resolver() { return request -> { if (request .getPath() .subPath(0) .value() - .startsWith("/employee")) return Mono.just(employeesAuthenticationManager()); + .startsWith("/employee")) + return Mono.just(employeesAuthenticationManager()); return Mono.just(customersAuthenticationManager()); }; } @@ -55,7 +55,11 @@ public class AuthResolverSecurityConfig { .switchIfEmpty(Mono.error(new UsernameNotFoundException(authentication .getPrincipal() .toString()))) - .map(b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))); + .map(b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), + authentication.getCredentials(), + Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")) + ) + ); } public ReactiveAuthenticationManager employeesAuthenticationManager() { @@ -63,7 +67,12 @@ public class AuthResolverSecurityConfig { .switchIfEmpty(Mono.error(new UsernameNotFoundException(authentication .getPrincipal() .toString()))) - .map(b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))); + .map( + b -> new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), + authentication.getCredentials(), + Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")) + ) + ); } public Mono customer(Authentication authentication) { diff --git a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java b/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java index 21c25a6111..691243b3ea 100644 --- a/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java +++ b/spring-5-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java @@ -14,7 +14,8 @@ import org.springframework.util.Base64Utils; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class AuthResolverIntegrationTest { - @Autowired private WebTestClient testClient; + @Autowired + private WebTestClient testClient; @Test public void givenCustomerCredential_whenWelcomeCustomer_thenExpectOk() { diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java b/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java similarity index 57% rename from spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java rename to spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java index 6f8931eb7a..ec168e2897 100644 --- a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverWebSecurityConfigurer.java +++ b/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java @@ -1,12 +1,11 @@ package com.baeldung.authresolver; -import java.util.Arrays; +import java.util.Collections; import javax.servlet.http.HttpServletRequest; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManagerResolver; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; @@ -18,17 +17,18 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationCo import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @Configuration -public class AuthResolverWebSecurityConfigurer extends WebSecurityConfigurerAdapter { +public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter { public AuthenticationConverter authenticationConverter() { return new BasicAuthenticationConverter(); } - public AuthenticationManagerResolver authenticationManagerResolver() { + public AuthenticationManagerResolver resolver() { return request -> { if (request .getPathInfo() - .startsWith("/employee")) return employeesAuthenticationManager(); + .startsWith("/employee")) + return employeesAuthenticationManager(); return customersAuthenticationManager(); }; } @@ -36,7 +36,11 @@ public class AuthResolverWebSecurityConfigurer extends WebSecurityConfigurerAdap public AuthenticationManager customersAuthenticationManager() { return authentication -> { if (isCustomer(authentication)) { - return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + return new UsernamePasswordAuthenticationToken( + authentication.getPrincipal(), + authentication.getCredentials(), + Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")) + ); } throw new UsernameNotFoundException(authentication .getPrincipal() @@ -44,31 +48,35 @@ public class AuthResolverWebSecurityConfigurer extends WebSecurityConfigurerAdap }; } - public boolean isCustomer(Authentication authentication) { + private boolean isCustomer(Authentication authentication) { return (authentication .getPrincipal() .toString() .startsWith("customer")); } - public boolean isEmployee(Authentication authentication) { + private boolean isEmployee(Authentication authentication) { return (authentication .getPrincipal() .toString() .startsWith("employee")); } - public AuthenticationFilter authenticationFilter(AuthenticationManagerResolver resolver, AuthenticationConverter converter) { - AuthenticationFilter ret = new AuthenticationFilter(resolver, converter); - ret.setSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> { - }); + private AuthenticationFilter authenticationFilter() { + AuthenticationFilter ret = new AuthenticationFilter( + resolver(), authenticationConverter()); + ret.setSuccessHandler((request, response, auth) -> {}); return ret; } - public AuthenticationManager employeesAuthenticationManager() { + private AuthenticationManager employeesAuthenticationManager() { return authentication -> { if (isEmployee(authentication)) { - return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + return new UsernamePasswordAuthenticationToken( + authentication.getPrincipal(), + authentication.getCredentials(), + Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")) + ); } throw new UsernameNotFoundException(authentication .getPrincipal() @@ -77,16 +85,11 @@ public class AuthResolverWebSecurityConfigurer extends WebSecurityConfigurerAdap } @Override - protected void configure(HttpSecurity http) throws Exception { - http - .addFilterBefore( - authenticationFilter( - authenticationManagerResolver(), authenticationConverter()), - BasicAuthenticationFilter.class); + protected void configure(HttpSecurity http) { + http.addFilterBefore( + authenticationFilter(), + BasicAuthenticationFilter.class + ); } - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - super.configure(auth); - } } diff --git a/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java b/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java index 0b0289e9e5..c87f8c1a3a 100644 --- a/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java +++ b/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java @@ -23,9 +23,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class AuthResolverIntegrationTest { - @Autowired private FilterChainProxy springSecurityFilterChain; + @Autowired + private FilterChainProxy springSecurityFilterChain; - @Autowired private WebApplicationContext wac; + @Autowired + private WebApplicationContext wac; private MockMvc mockMvc; From d78833dd9e73125e256c94d82c14562696a8738e Mon Sep 17 00:00:00 2001 From: maryarm Date: Sat, 14 Dec 2019 19:26:34 +0330 Subject: [PATCH 3/3] BAEL-3338: A Guide to AuthenticationManagerResolver in Spring Security -Fix issues according to review --- .../reactive/authresolver/CustomWebSecurityConfig.java | 3 ++- .../authresolver/CustomWebSecurityConfigurer.java | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java index cd5a0af5a2..d07a991089 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java @@ -44,8 +44,9 @@ public class CustomWebSecurityConfig { .getPath() .subPath(0) .value() - .startsWith("/employee")) + .startsWith("/employee")) { return Mono.just(employeesAuthenticationManager()); + } return Mono.just(customersAuthenticationManager()); }; } diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java b/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java index ec168e2897..33ef692173 100644 --- a/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java +++ b/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java @@ -27,8 +27,9 @@ public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter { return request -> { if (request .getPathInfo() - .startsWith("/employee")) + .startsWith("/employee")) { return employeesAuthenticationManager(); + } return customersAuthenticationManager(); }; } @@ -63,10 +64,10 @@ public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter { } private AuthenticationFilter authenticationFilter() { - AuthenticationFilter ret = new AuthenticationFilter( + AuthenticationFilter filter = new AuthenticationFilter( resolver(), authenticationConverter()); - ret.setSuccessHandler((request, response, auth) -> {}); - return ret; + filter.setSuccessHandler((request, response, auth) -> {}); + return filter; } private AuthenticationManager employeesAuthenticationManager() {