2
0
Эх сурвалжийг харах

HttpSecurity.authorizeExchange() allows Method Chaining

Fixes gh-4397
Rob Winch 8 жил өмнө
parent
commit
ca6348800e

+ 0 - 93
config/src/main/java/org/springframework/security/config/web/server/AuthorizeExchangeBuilder.java

@@ -1,93 +0,0 @@
-/*
- * 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.config.web.server;
-
-import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.web.server.authorization.AuthorizationContext;
-import org.springframework.security.authorization.ReactiveAuthorizationManager;
-import org.springframework.security.authorization.AuthorityAuthorizationManager;
-import org.springframework.security.web.server.authorization.AuthorizationWebFilter;
-import org.springframework.security.web.server.authorization.DelegatingReactiveAuthorizationManager;
-import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
-import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcherEntry;
-import org.springframework.web.server.WebFilter;
-import reactor.core.publisher.Mono;
-
-/**
- * @author Rob Winch
- * @since 5.0
- */
-public class AuthorizeExchangeBuilder extends AbstractServerWebExchangeMatcherRegistry<AuthorizeExchangeBuilder.Access> {
-	private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager.builder();
-	private ServerWebExchangeMatcher matcher;
-	private boolean anyExchangeRegistered;
-
-	@Override
-	public Access anyExchange() {
-		Access result = super.anyExchange();
-		anyExchangeRegistered = true;
-		return result;
-	}
-
-	@Override
-	protected Access registerMatcher(ServerWebExchangeMatcher matcher) {
-		if(anyExchangeRegistered) {
-			throw new IllegalStateException("Cannot register " + matcher + " which would be unreachable because anyExchange() has already been registered.");
-		}
-		if(this.matcher != null) {
-			throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined");
-		}
-		this.matcher = matcher;
-		return new Access();
-	}
-
-	public WebFilter build() {
-		if(this.matcher != null) {
-			throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined");
-		}
-		return new AuthorizationWebFilter(managerBldr.build());
-	}
-
-	public final class Access {
-
-		public AuthorizeExchangeBuilder permitAll() {
-			return access( (a,e) -> Mono.just(new AuthorizationDecision(true)));
-		}
-
-		public AuthorizeExchangeBuilder denyAll() {
-			return access( (a,e) -> Mono.just(new AuthorizationDecision(false)));
-		}
-
-		public AuthorizeExchangeBuilder hasRole(String role) {
-			return access(AuthorityAuthorizationManager.hasRole(role));
-		}
-
-		public AuthorizeExchangeBuilder hasAuthority(String authority) {
-			return access(AuthorityAuthorizationManager.hasAuthority(authority));
-		}
-
-		public AuthorizeExchangeBuilder authenticated() {
-			return access(AuthenticatedAuthorizationManager.authenticated());
-		}
-
-		public AuthorizeExchangeBuilder access(ReactiveAuthorizationManager<AuthorizationContext> manager) {
-			managerBldr.add(new ServerWebExchangeMatcherEntry<>(matcher, manager));
-			matcher = null;
-			return AuthorizeExchangeBuilder.this;
-		}
-	}
-}

+ 78 - 0
config/src/main/java/org/springframework/security/config/web/server/HttpSecurity.java

@@ -20,15 +20,24 @@ import java.util.List;
 import java.util.Optional;
 
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
+import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
+import org.springframework.security.authorization.AuthorityAuthorizationManager;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.ReactiveAuthorizationManager;
 import org.springframework.security.web.server.MatcherSecurityWebFilterChain;
 import org.springframework.security.web.server.SecurityWebFilterChain;
+import org.springframework.security.web.server.authorization.AuthorizationContext;
+import org.springframework.security.web.server.authorization.AuthorizationWebFilter;
+import org.springframework.security.web.server.authorization.DelegatingReactiveAuthorizationManager;
 import org.springframework.security.web.server.context.SecurityContextRepositoryWebFilter;
 import org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter;
 import org.springframework.security.web.server.context.SecurityContextRepository;
 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.util.Assert;
 import org.springframework.web.server.WebFilter;
+import reactor.core.publisher.Mono;
 
 /**
  * @author Rob Winch
@@ -129,4 +138,73 @@ public class HttpSecurity {
 	}
 
 	private HttpSecurity() {}
+
+	/**
+	 * @author Rob Winch
+	 * @since 5.0
+	 */
+	public class AuthorizeExchangeBuilder extends AbstractServerWebExchangeMatcherRegistry<AuthorizeExchangeBuilder.Access> {
+		private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager.builder();
+		private ServerWebExchangeMatcher matcher;
+		private boolean anyExchangeRegistered;
+
+		public HttpSecurity and() {
+			return HttpSecurity.this;
+		}
+
+		@Override
+		public Access anyExchange() {
+			Access result = super.anyExchange();
+			anyExchangeRegistered = true;
+			return result;
+		}
+
+		@Override
+		protected Access registerMatcher(ServerWebExchangeMatcher matcher) {
+			if(anyExchangeRegistered) {
+				throw new IllegalStateException("Cannot register " + matcher + " which would be unreachable because anyExchange() has already been registered.");
+			}
+			if(this.matcher != null) {
+				throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined");
+			}
+			this.matcher = matcher;
+			return new Access();
+		}
+
+		protected WebFilter build() {
+			if(this.matcher != null) {
+				throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined");
+			}
+			return new AuthorizationWebFilter(managerBldr.build());
+		}
+
+		public final class Access {
+
+			public AuthorizeExchangeBuilder permitAll() {
+				return access( (a,e) -> Mono.just(new AuthorizationDecision(true)));
+			}
+
+			public AuthorizeExchangeBuilder denyAll() {
+				return access( (a,e) -> Mono.just(new AuthorizationDecision(false)));
+			}
+
+			public AuthorizeExchangeBuilder hasRole(String role) {
+				return access(AuthorityAuthorizationManager.hasRole(role));
+			}
+
+			public AuthorizeExchangeBuilder hasAuthority(String authority) {
+				return access(AuthorityAuthorizationManager.hasAuthority(authority));
+			}
+
+			public AuthorizeExchangeBuilder authenticated() {
+				return access(AuthenticatedAuthorizationManager.authenticated());
+			}
+
+			public AuthorizeExchangeBuilder access(ReactiveAuthorizationManager<AuthorizationContext> manager) {
+				managerBldr.add(new ServerWebExchangeMatcherEntry<>(matcher, manager));
+				matcher = null;
+				return AuthorizeExchangeBuilder.this;
+			}
+		}
+	}
 }

+ 1 - 1
config/src/test/java/org/springframework/security/config/web/server/AuthorizeExchangeBuilderTests.java

@@ -29,7 +29,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
  * @since 5.0
  */
 public class AuthorizeExchangeBuilderTests {
-	AuthorizeExchangeBuilder authorization = new AuthorizeExchangeBuilder();
+	HttpSecurity.AuthorizeExchangeBuilder authorization = HttpSecurity.http().new AuthorizeExchangeBuilder();
 
 	@Test
 	public void antMatchersWhenMethodAndPatternsThenDiscriminatesByMethod() {

+ 1 - 1
config/src/test/java/org/springframework/security/config/web/server/HttpSecurityTests.java

@@ -83,7 +83,7 @@ public class HttpSecurityTests {
 		http.securityContextRepository(new WebSessionSecurityContextRepository());
 		http.httpBasic();
 		http.authenticationManager(authenticationManager);
-		AuthorizeExchangeBuilder authorize = http.authorizeExchange();
+		HttpSecurity.AuthorizeExchangeBuilder authorize = http.authorizeExchange();
 		authorize.anyExchange().authenticated();
 
 		WebTestClient client = buildClient();

+ 7 - 6
samples/javaconfig/hellowebflux/src/main/java/sample/SecurityConfig.java

@@ -39,12 +39,13 @@ public class SecurityConfig {
 
 	@Bean
 	SecurityWebFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
-		http.authorizeExchange()
-			.pathMatchers("/admin/**").hasRole("ADMIN")
-			.pathMatchers("/users/{user}/**").access(this::currentUserMatchesPath)
-			.anyExchange().authenticated();
-
-		return http.build();
+		return http
+			.authorizeExchange()
+				.pathMatchers("/admin/**").hasRole("ADMIN")
+				.pathMatchers("/users/{user}/**").access(this::currentUserMatchesPath)
+				.anyExchange().authenticated()
+				.and()
+			.build();
 	}
 
 	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {

+ 7 - 6
samples/javaconfig/hellowebfluxfn/src/main/java/sample/SecurityConfig.java

@@ -40,12 +40,13 @@ public class SecurityConfig {
 
 	@Bean
 	SecurityWebFilterChain httpSecurity(HttpSecurity http) throws Exception {
-		http.authorizeExchange()
-			.pathMatchers("/admin/**").hasRole("ADMIN")
-			.pathMatchers("/users/{user}/**").access(this::currentUserMatchesPath)
-			.anyExchange().authenticated();
-
-		return http.build();
+		return http
+			.authorizeExchange()
+				.pathMatchers("/admin/**").hasRole("ADMIN")
+				.pathMatchers("/users/{user}/**").access(this::currentUserMatchesPath)
+				.anyExchange().authenticated()
+				.and()
+			.build();
 	}
 
 	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {