Browse Source

Add @EnableWebFluxSecurity

Fixes gh-4344
Rob Winch 8 years ago
parent
commit
0428cdd934

+ 36 - 0
config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java

@@ -0,0 +1,36 @@
+/*
+ *
+ *  * 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.annotation.web.reactive;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Rob Winch
+ * @since 5.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Documented
+@Import(WebFluxSecurityConfiguration.class)
+@Configuration
+public @interface EnableWebFluxSecurity {
+}

+ 79 - 0
config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java

@@ -0,0 +1,79 @@
+/*
+ *
+ *  * 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.annotation.web.reactive;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.ReactiveAdapterRegistry;
+import org.springframework.security.authentication.ReactiveAuthenticationManager;
+import org.springframework.security.authentication.UserDetailsRepository;
+import org.springframework.security.authentication.UserDetailsRepositoryAuthenticationManager;
+import org.springframework.security.config.web.server.HttpSecurity;
+import org.springframework.security.web.reactive.result.method.annotation.AuthenticationPrincipalArgumentResolver;
+import org.springframework.security.web.server.context.WebSessionSecurityContextRepository;
+import org.springframework.web.reactive.config.WebFluxConfigurer;
+import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
+
+import static org.springframework.security.config.web.server.HttpSecurity.http;
+
+/**
+ * @author Rob Winch
+ * @since 5.0
+ */
+@Configuration
+public class WebFluxSecurityConfiguration implements WebFluxConfigurer {
+	@Autowired(required = false)
+	private ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
+
+	@Autowired(required = false)
+	private ReactiveAuthenticationManager authenticationManager;
+
+	@Autowired(required = false)
+	private UserDetailsRepository userDetailsRepository;
+
+	@Override
+	public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
+		configurer.addCustomResolver(authenticationPrincipalArgumentResolver());
+	}
+
+	@Bean
+	public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() {
+		return new AuthenticationPrincipalArgumentResolver(adapterRegistry);
+	}
+
+	@Bean
+	public HttpSecurity httpSecurity() {
+		HttpSecurity http = http();
+		http.authenticationManager(authenticationManager());
+		http.securityContextRepository(new WebSessionSecurityContextRepository());
+		return http;
+	}
+
+	private ReactiveAuthenticationManager authenticationManager() {
+		if(authenticationManager != null) {
+			return authenticationManager;
+		}
+		if(userDetailsRepository != null) {
+			return new UserDetailsRepositoryAuthenticationManager(userDetailsRepository);
+		}
+		return null;
+	}
+}

+ 1 - 56
samples/javaconfig/hellowebflux/src/main/java/sample/HelloWebfluxApplication.java

@@ -16,36 +16,19 @@
 
 package sample;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 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.context.annotation.Configuration;
-import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.http.server.reactive.HttpHandler;
 import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
-import org.springframework.security.authentication.ReactiveAuthenticationManager;
-import org.springframework.security.authentication.UserDetailsRepositoryAuthenticationManager;
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.config.web.server.AuthorizeExchangeBuilder;
-import org.springframework.security.config.web.server.HttpSecurity;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.reactive.result.method.annotation.AuthenticationPrincipalArgumentResolver;
-import org.springframework.security.web.server.authorization.AuthorizationContext;
-import org.springframework.security.web.server.context.WebSessionSecurityContextRepository;
 import org.springframework.web.reactive.DispatcherHandler;
 import org.springframework.web.reactive.config.EnableWebFlux;
-import org.springframework.web.reactive.config.WebFluxConfigurer;
-import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
-import org.springframework.web.server.WebFilter;
-import reactor.core.publisher.Mono;
 import reactor.ipc.netty.NettyContext;
 import reactor.ipc.netty.http.server.HttpServer;
 
-import static org.springframework.security.config.web.server.HttpSecurity.http;
-
 /**
  * @author Rob Winch
  * @since 5.0
@@ -53,24 +36,16 @@ import static org.springframework.security.config.web.server.HttpSecurity.http;
 @Configuration
 @EnableWebFlux
 @ComponentScan
-public class HelloWebfluxApplication implements WebFluxConfigurer {
+public class HelloWebfluxApplication {
 	@Value("${server.port:8080}")
 	private int port = 8080;
 
-	@Autowired
-	private ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
-
 	public static void main(String[] args) throws Exception {
 		try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWebfluxApplication.class)) {
 			context.getBean(NettyContext.class).onClose().block();
 		}
 	}
 
-	@Override
-	public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
-		configurer.addCustomResolver(authenticationPrincipalArgumentResolver());
-	}
-
 	@Bean
 	public NettyContext nettyContext(ApplicationContext context) {
 		HttpHandler handler = DispatcherHandler.toHttpHandler(context);
@@ -78,34 +53,4 @@ public class HelloWebfluxApplication implements WebFluxConfigurer {
 		HttpServer httpServer = HttpServer.create("localhost", port);
 		return httpServer.newHandler(adapter).block();
 	}
-
-	@Bean
-	public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() {
-		return new AuthenticationPrincipalArgumentResolver(adapterRegistry);
-	}
-
-	@Bean
-	WebFilter springSecurityFilterChain(ReactiveAuthenticationManager manager) throws Exception {
-		HttpSecurity http = http();
-		http.securityContextRepository(new WebSessionSecurityContextRepository());
-		http.authenticationManager(manager);
-		http.httpBasic();
-
-		AuthorizeExchangeBuilder authorize = http.authorizeExchange();
-		authorize.antMatchers("/admin/**").hasRole("ADMIN");
-		authorize.antMatchers("/users/{user}/**").access(this::currentUserMatchesPath);
-		authorize.anyExchange().authenticated();
-		return http.build();
-	}
-
-	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {
-		return authentication
-			.map( a -> context.getVariables().get("user").equals(a.getName()))
-			.map( granted -> new AuthorizationDecision(granted));
-	}
-
-	@Bean
-	public ReactiveAuthenticationManager authenticationManager(UserRepositoryUserDetailsRepository udr) {
-		return new UserDetailsRepositoryAuthenticationManager(udr);
-	}
 }

+ 54 - 0
samples/javaconfig/hellowebflux/src/main/java/sample/SecurityConfig.java

@@ -0,0 +1,54 @@
+/*
+ *
+ *  * 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 sample;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.AuthorizeExchangeBuilder;
+import org.springframework.security.config.web.server.HttpSecurity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.server.authorization.AuthorizationContext;
+import org.springframework.web.server.WebFilter;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author Rob Winch
+ * @since 5.0
+ */
+@EnableWebFluxSecurity
+public class SecurityConfig {
+
+	@Bean
+	WebFilter springSecurityFilterChain(HttpSecurity http) throws Exception {
+		http.httpBasic();
+
+		AuthorizeExchangeBuilder authorize = http.authorizeExchange();
+		authorize.antMatchers("/admin/**").hasRole("ADMIN");
+		authorize.antMatchers("/users/{user}/**").access(this::currentUserMatchesPath);
+		authorize.anyExchange().authenticated();
+		return http.build();
+	}
+
+	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {
+		return authentication
+			.map( a -> context.getVariables().get("user").equals(a.getName()))
+			.map( granted -> new AuthorizationDecision(granted));
+	}
+}

+ 0 - 24
samples/javaconfig/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnApplication.java

@@ -90,28 +90,4 @@ public class HelloWebfluxFnApplication {
 		return RouterFunctions.toHttpHandler(route, handlerStrategies);
 	}
 
-	@Bean
-	WebFilter springSecurityFilterChain(ReactiveAuthenticationManager manager) throws Exception {
-		HttpSecurity http = http();
-		http.securityContextRepository(new WebSessionSecurityContextRepository());
-		http.authenticationManager(manager);
-		http.httpBasic();
-
-		AuthorizeExchangeBuilder authorize = http.authorizeExchange();
-		authorize.antMatchers("/admin/**").hasRole("ADMIN");
-		authorize.antMatchers("/users/{user}/**").access(this::currentUserMatchesPath);
-		authorize.anyExchange().authenticated();
-		return http.build();
-	}
-
-	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {
-		return authentication
-			.map( a -> context.getVariables().get("user").equals(a.getName()))
-			.map( granted -> new AuthorizationDecision(granted));
-	}
-
-	@Bean
-	public ReactiveAuthenticationManager authenticationManager(UserRepositoryUserDetailsRepository udr) {
-		return new UserDetailsRepositoryAuthenticationManager(udr);
-	}
 }

+ 54 - 0
samples/javaconfig/hellowebfluxfn/src/main/java/sample/SecurityConfig.java

@@ -0,0 +1,54 @@
+/*
+ *
+ *  * 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 sample;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.AuthorizeExchangeBuilder;
+import org.springframework.security.config.web.server.HttpSecurity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.server.authorization.AuthorizationContext;
+import org.springframework.web.server.WebFilter;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author Rob Winch
+ * @since 5.0
+ */
+@EnableWebFluxSecurity
+public class SecurityConfig {
+
+	@Bean
+	WebFilter springSecurityFilterChain(HttpSecurity http) throws Exception {
+		http.httpBasic();
+
+		AuthorizeExchangeBuilder authorize = http.authorizeExchange();
+		authorize.antMatchers("/admin/**").hasRole("ADMIN");
+		authorize.antMatchers("/users/{user}/**").access(this::currentUserMatchesPath);
+		authorize.anyExchange().authenticated();
+		return http.build();
+	}
+
+	private Mono<AuthorizationDecision> currentUserMatchesPath(Mono<Authentication> authentication, AuthorizationContext context) {
+		return authentication
+			.map( a -> context.getVariables().get("user").equals(a.getName()))
+			.map( granted -> new AuthorizationDecision(granted));
+	}
+}