Add Multiple Reactive HttpSecurity

Fixes gh-4395
This commit is contained in:
Rob Winch
2017-06-14 14:05:52 -05:00
parent 406e1e6951
commit 9141a8a7c0
10 changed files with 281 additions and 15 deletions

View File

@@ -0,0 +1,56 @@
/*
*
* * Copyright 2002-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.security.web.server;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
/**
* @author Rob Winch
* @since 5.0
*/
public class MatcherSecurityWebFilterChain implements SecurityWebFilterChain {
private final ServerWebExchangeMatcher matcher;
private final Flux<WebFilter> filters;
public MatcherSecurityWebFilterChain(ServerWebExchangeMatcher matcher, List<WebFilter> filters) {
this(matcher, Flux.fromIterable(filters));
}
public MatcherSecurityWebFilterChain(ServerWebExchangeMatcher matcher, Flux<WebFilter> filters) {
this.matcher = matcher;
this.filters = filters;
}
@Override
public Mono<Boolean> matches(ServerWebExchange exchange) {
return matcher.matches(exchange)
.map( m -> m.isMatch() );
}
@Override
public Flux<WebFilter> getWebFilters() {
return filters;
}
}

View File

@@ -0,0 +1,35 @@
/*
*
* * Copyright 2002-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.security.web.server;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @author Rob Winch
* @since 5.0
*/
public interface SecurityWebFilterChain {
Mono<Boolean> matches(ServerWebExchange exchange);
Flux<WebFilter> getWebFilters();
}

View File

@@ -17,15 +17,21 @@
*/
package org.springframework.security.web.server;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcherEntry;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.handler.DefaultWebFilterChain;
import org.springframework.web.server.handler.FilteringWebHandler;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
@@ -33,16 +39,34 @@ import reactor.core.publisher.Mono;
* @since 5.0
*/
public class WebFilterChainFilter implements WebFilter {
private final List<WebFilter> filters;
private final Flux<SecurityWebFilterChain> filters;
public WebFilterChainFilter(List<WebFilter> filters) {
super();
public WebFilterChainFilter(Flux<SecurityWebFilterChain> filters) {
this.filters = filters;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
DefaultWebFilterChain delegate = new DefaultWebFilterChain(new FilteringWebHandler(e -> chain.filter(e), filters));
return delegate.filter(exchange);
return filters
.filterWhen( securityWebFilterChain -> securityWebFilterChain.matches(exchange))
.next()
.flatMap( securityWebFilterChain -> securityWebFilterChain.getWebFilters()
.collectList()
)
.map( filters -> new FilteringWebHandler(webHandler -> chain.filter(webHandler), filters))
.map( handler -> new DefaultWebFilterChain(handler) )
.flatMap( securedChain -> securedChain.filter(exchange));
}
public static WebFilterChainFilter fromWebFiltersList(List<WebFilter> filters) {
return new WebFilterChainFilter(Flux.just(new MatcherSecurityWebFilterChain(ServerWebExchangeMatchers.anyExchange(), filters)));
}
public static WebFilterChainFilter fromSecurityWebFilterChainsList(List<SecurityWebFilterChain> securityWebFilterChains) {
return new WebFilterChainFilter(Flux.fromIterable(securityWebFilterChains));
}
public static WebFilterChainFilter fromSecurityWebFilterChains(SecurityWebFilterChain... securityWebFilterChains) {
return fromSecurityWebFilterChainsList(Arrays.asList(securityWebFilterChains));
}
}