Updates for boot 2 and spring security 5
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security-reactive</artifactId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -40,6 +40,7 @@ class GatewayRedisAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
//TODO: replace with ReactiveStringRedisTemplate in future
|
||||
public ReactiveRedisTemplate<String, String> stringReactiveRedisTemplate(
|
||||
ReactiveRedisConnectionFactory reactiveRedisConnectionFactory,
|
||||
ResourceLoader resourceLoader) {
|
||||
@@ -57,7 +58,7 @@ class GatewayRedisAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public RedisRateLimiter redisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate,
|
||||
@Qualifier("redisRequestRateLimiterScript") RedisScript<String> redisScript) {
|
||||
@Qualifier("redisRequestRateLimiterScript") RedisScript<List<Long>> redisScript) {
|
||||
return new RedisRateLimiter(redisTemplate, redisScript);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ public class RedisRateLimiter implements RateLimiter {
|
||||
private Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private final ReactiveRedisTemplate<String, String> redisTemplate;
|
||||
private final RedisScript script;
|
||||
private final RedisScript<List<Long>> script;
|
||||
|
||||
public RedisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate,
|
||||
RedisScript script) {
|
||||
RedisScript<List<Long>> script) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.script = script;
|
||||
}
|
||||
@@ -57,13 +57,13 @@ public class RedisRateLimiter implements RateLimiter {
|
||||
List<String> args = Arrays.asList(replenishRate + "", burstCapacity + "",
|
||||
Instant.now().getEpochSecond() + "", "1");
|
||||
// allowed, tokens_left = redis.eval(SCRIPT, keys, args)
|
||||
Flux<Long> flux = this.redisTemplate.execute(this.script, keys, args)
|
||||
Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, args)
|
||||
.log("redisratelimiter", Level.FINER);
|
||||
return flux.onErrorResume(throwable -> Flux.just(1L, -1L))
|
||||
return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L)))
|
||||
.reduce(new ArrayList<Long>(), (longs, l) -> {
|
||||
longs.add(l);
|
||||
longs.addAll(l);
|
||||
return longs;
|
||||
}).map(results -> {
|
||||
}) .map(results -> {
|
||||
boolean allowed = results.get(0) == 1L;
|
||||
Long tokensLeft = results.get(1);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class RequestRateLimiterGatewayFilterFactoryTests extends BaseWebClientTe
|
||||
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
MockServerWebExchange exchange = new MockServerWebExchange(request);
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.OK);
|
||||
|
||||
when(this.filterChain.filter(exchange)).thenReturn(Mono.empty());
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -61,7 +61,7 @@ public class RewritePathGatewayFilterFactoryTests {
|
||||
.get("http://localhost"+ actualPath)
|
||||
.build();
|
||||
|
||||
ServerWebExchange exchange = new MockServerWebExchange(request);
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
GatewayFilterChain filterChain = mock(GatewayFilterChain.class);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
@@ -69,7 +69,7 @@ public class SetPathGatewayFilterFactoryTests {
|
||||
.get("http://localhost"+ actualPath)
|
||||
.build();
|
||||
|
||||
ServerWebExchange exchange = new MockServerWebExchange(request);
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
try {
|
||||
Constructor<PathMatchInfo> constructor = ReflectionUtils.accessibleConstructor(PathMatchInfo.class, Map.class, Map.class);
|
||||
|
||||
@@ -18,8 +18,8 @@ import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewa
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.Routes;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.web.server.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.MapUserDetailsRepository;
|
||||
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;
|
||||
@@ -32,9 +32,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
|
||||
import static org.springframework.cloud.gateway.filter.factory.GatewayFilters.prefixPath;
|
||||
import static org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory.BURST_CAPACITY_KEY;
|
||||
import static org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory.REPLENISH_RATE_KEY;
|
||||
import static org.springframework.cloud.gateway.filter.factory.GatewayFilters.prefixPath;
|
||||
import static org.springframework.cloud.gateway.handler.predicate.RoutePredicates.path;
|
||||
import static org.springframework.tuple.TupleBuilder.tuple;
|
||||
import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
|
||||
@@ -112,7 +112,7 @@ public class PrincipalNameKeyResolverIntegrationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityWebFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
|
||||
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
|
||||
return http.httpBasic().and()
|
||||
.authorizeExchange()
|
||||
.pathMatchers("/myapi/**").authenticated()
|
||||
@@ -122,9 +122,9 @@ public class PrincipalNameKeyResolverIntegrationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MapUserDetailsRepository userDetailsRepository() {
|
||||
UserDetails user = User.withUsername("user").password("password").roles("USER").build();
|
||||
return new MapUserDetailsRepository(user);
|
||||
public MapReactiveUserDetailsService reactiveUserDetailsService() {
|
||||
UserDetails user = User.withUsername("user").password("{noop}password").roles("USER").build();
|
||||
return new MapReactiveUserDetailsService(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.time.format.DateTimeFormatter;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -128,6 +128,6 @@ public class BetweenRoutePredicateFactoryTests {
|
||||
|
||||
static ServerWebExchange getExchange() {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("http://example.com").build();
|
||||
return new MockServerWebExchange(request);
|
||||
return MockServerWebExchange.from(request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.cloud.gateway.handler.predicate;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -59,17 +59,17 @@ public class RoutePredicatesTest {
|
||||
private ServerWebExchange mockHostExchange(String host) {
|
||||
MockServerHttpRequest mockRequest = MockServerHttpRequest.get("/")
|
||||
.header("Host", host).build();
|
||||
return new MockServerWebExchange(mockRequest);
|
||||
return MockServerWebExchange.from(mockRequest);
|
||||
}
|
||||
|
||||
private ServerWebExchange mockPathExchange(String path) {
|
||||
MockServerHttpRequest mockRequest = MockServerHttpRequest.get(path).build();
|
||||
return new MockServerWebExchange(mockRequest);
|
||||
return MockServerWebExchange.from(mockRequest);
|
||||
}
|
||||
|
||||
private ServerWebExchange mockMethodExchange(String method) {
|
||||
MockServerHttpRequest mockRequest = MockServerHttpRequest
|
||||
.method(HttpMethod.resolve(method), "/").build();
|
||||
return new MockServerWebExchange(mockRequest);
|
||||
return MockServerWebExchange.from(mockRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
@@ -100,7 +101,7 @@ public class BaseWebClientTests {
|
||||
return "httpbin compatible home";
|
||||
}
|
||||
|
||||
@RequestMapping("/headers")
|
||||
@RequestMapping(path = "/headers", method = {RequestMethod.GET, RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Map<String, Object> headers(ServerWebExchange exchange) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
addHeaders(exchange, map);
|
||||
@@ -116,14 +117,14 @@ public class BaseWebClientTests {
|
||||
map.put("headers", headers);
|
||||
}
|
||||
|
||||
@RequestMapping("/delay/{sec}")
|
||||
@RequestMapping(path = "/delay/{sec}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Map<String, Object> get(ServerWebExchange exchange, @PathVariable int sec) throws InterruptedException {
|
||||
int delay = Math.min(sec, 10);
|
||||
Thread.sleep(delay * 1000);
|
||||
return get(exchange);
|
||||
}
|
||||
|
||||
@RequestMapping("/get")
|
||||
@RequestMapping(path = "/get", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Map<String, Object> get(ServerWebExchange exchange) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
addHeaders(exchange, map);
|
||||
@@ -136,7 +137,7 @@ public class BaseWebClientTests {
|
||||
return map;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Mono<Map<String, Object>> postFormData(@RequestBody Mono<MultiValueMap<String, Part>> parts) {
|
||||
// StringDecoder decoder = StringDecoder.allMimeTypes(true);
|
||||
return parts.flux().flatMap(map -> Flux.fromIterable(map.values()))
|
||||
@@ -150,12 +151,12 @@ public class BaseWebClientTests {
|
||||
}).map(files -> Collections.singletonMap("files", files));
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/post", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@RequestMapping(path = "/post", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Mono<Map<String, Object>> postUrlEncoded(ServerWebExchange exchange) throws IOException {
|
||||
return post(exchange, null);
|
||||
}
|
||||
|
||||
@RequestMapping("/post")
|
||||
@RequestMapping(path = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Mono<Map<String, Object>> post(ServerWebExchange exchange,
|
||||
@RequestBody(required = false) String body) throws IOException {
|
||||
HashMap<String, Object> ret = new HashMap<>();
|
||||
|
||||
@@ -2,16 +2,17 @@ package org.springframework.cloud.gateway.test;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.web.server.HttpSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
|
||||
@Configuration
|
||||
public class PermitAllSecurityConfiguration {
|
||||
@Bean
|
||||
SecurityWebFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
|
||||
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
|
||||
return http.authorizeExchange()
|
||||
.anyExchange().permitAll()
|
||||
.and()
|
||||
.csrf().disable()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.springframework.cloud.gateway.filter.factory.GatewayFilters.addRespon
|
||||
import org.springframework.cloud.gateway.handler.predicate.RoutePredicates.host
|
||||
import org.springframework.cloud.gateway.handler.predicate.RoutePredicates.path
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest
|
||||
import org.springframework.mock.http.server.reactive.MockServerWebExchange
|
||||
import org.springframework.mock.web.server.MockServerWebExchange
|
||||
import org.springframework.web.server.ServerWebExchange
|
||||
import reactor.test.StepVerifier
|
||||
import java.net.URI
|
||||
@@ -42,7 +42,7 @@ class GatewayDslTests {
|
||||
.expectComplete()
|
||||
.verify()
|
||||
|
||||
val sampleExchange: ServerWebExchange = MockServerWebExchange(MockServerHttpRequest.get("/image/webp")
|
||||
val sampleExchange: ServerWebExchange = MockServerWebExchange.from(MockServerHttpRequest.get("/image/webp")
|
||||
.header("Host", "test.abc.org").build())
|
||||
|
||||
val filteredRoutes = routeLocator.routes.filter({ r -> r.predicate.test(sampleExchange) })
|
||||
|
||||
Reference in New Issue
Block a user