49 changed files with 3207 additions and 0 deletions
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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; |
||||
|
||||
/** |
||||
* A {@link Customizer} that allows invocation of code that throws a checked exception. |
||||
* |
||||
* @param <T> The type of input. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface ThrowingCustomizer<T> extends Customizer<T> { |
||||
|
||||
/** |
||||
* Default {@link Customizer#customize(Object)} that wraps any thrown checked |
||||
* exceptions (by default in a {@link RuntimeException}). |
||||
* @param t the object to customize |
||||
*/ |
||||
default void customize(T t) { |
||||
try { |
||||
customizeWithException(t); |
||||
} |
||||
catch (RuntimeException ex) { |
||||
throw ex; |
||||
} |
||||
catch (Exception ex) { |
||||
throw new RuntimeException(ex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Performs the customization on the given object, possibly throwing a checked |
||||
* exception. |
||||
* @param t the object to customize |
||||
* @throws Exception on error |
||||
*/ |
||||
void customizeWithException(T t) throws Exception; |
||||
|
||||
} |
||||
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.customizerbeanordering; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity; |
||||
import org.springframework.security.web.server.SecurityWebFilterChain; |
||||
import org.springframework.web.reactive.config.EnableWebFlux; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebFlux |
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class CustomizerBeanOrderingConfiguration { |
||||
|
||||
// tag::sample[]
|
||||
@Bean // <4>
|
||||
SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeExchange((exchange) -> exchange |
||||
.anyExchange().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <2>
|
||||
Customizer<ServerHttpSecurity> userAuthorization() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.authorizeExchange((exchange) -> exchange |
||||
.pathMatchers("/users/**").hasRole("USER") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <1>
|
||||
Customizer<ServerHttpSecurity> adminAuthorization() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.authorizeExchange((exchange) -> exchange |
||||
.pathMatchers("/admins/**").hasRole("ADMIN") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// <3>
|
||||
|
||||
@Bean |
||||
Customizer<ServerHttpSecurity.HeaderSpec> contentSecurityPolicy() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
.policyDirectives("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
Customizer<ServerHttpSecurity.HeaderSpec> contentTypeOptions() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentTypeOptions(Customizer.withDefaults()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
Customizer<ServerHttpSecurity.HttpsRedirectSpec> httpsRedirect() { |
||||
// @formatter:off
|
||||
return Customizer.withDefaults(); |
||||
// @formatter:on
|
||||
} |
||||
// end::sample[]
|
||||
|
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.customizerbeanordering; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.test.web.reactive.server.WebTestClient; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser; |
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class CustomizerBeanOrderingTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
private WebTestClient webTest; |
||||
|
||||
@Test |
||||
void authorizationOrdered() throws Exception { |
||||
this.spring.register( |
||||
CustomizerBeanOrderingConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.webTest.mutateWith(mockUser("admin").roles("ADMIN")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isOk(); |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden(); |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isOk(); |
||||
this.webTest.mutateWith(mockUser("user").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden(); |
||||
this.webTest.mutateWith(mockUser("authenticated").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/other") |
||||
.exchange() |
||||
.expectStatus().isOk(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.serverhttpsecuritycustomizerbean; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity; |
||||
import org.springframework.security.web.server.SecurityWebFilterChain; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class ServerHttpSecurityCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeExchange((exchange) -> exchange |
||||
.anyExchange().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// tag::httpSecurityCustomizer[]
|
||||
@Bean |
||||
Customizer<ServerHttpSecurity> httpSecurityCustomizer() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.headers((headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
// <1>
|
||||
.policyDirectives("object-src 'none'") |
||||
) |
||||
) |
||||
// <2>
|
||||
.redirectToHttps(Customizer.withDefaults()); |
||||
// @formatter:on
|
||||
} |
||||
// end::httpSecurityCustomizer[]
|
||||
|
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.serverhttpsecuritycustomizerbean; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.test.web.reactive.server.WebTestClient; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class ServerHttpSecurityCustomizerBeanTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
private WebTestClient webTest; |
||||
|
||||
@Test |
||||
void httpSecurityCustomizer() throws Exception { |
||||
this.spring.register( |
||||
ServerHttpSecurityCustomizerBeanConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader().location("https://localhost/") |
||||
.expectHeader() |
||||
.value("Content-Security-Policy", csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.toplevelcustomizerbean; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity; |
||||
import org.springframework.security.web.server.SecurityWebFilterChain; |
||||
import org.springframework.web.reactive.config.EnableWebFlux; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
public class TopLevelCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeExchange((exchange) -> exchange |
||||
.anyExchange().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// tag::headersCustomizer[]
|
||||
@Bean |
||||
Customizer<ServerHttpSecurity.HeaderSpec> headersSecurity() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
// <1>
|
||||
.policyDirectives("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
// end::headersCustomizer[]
|
||||
|
||||
} |
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.reactive.configuration.toplevelcustomizerbean; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.test.web.reactive.server.WebTestClient; |
||||
import org.springframework.test.web.servlet.ResultMatcher; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class TopLevelCustomizerBeanTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
private WebTestClient webTest; |
||||
|
||||
|
||||
@Test |
||||
void headersCustomizer() throws Exception { |
||||
this.spring.register(TopLevelCustomizerBeanConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader() |
||||
.value("Content-Security-Policy", csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
private static @NotNull ResultMatcher cspIsObjectSrcNone() { |
||||
return header().string("Content-Security-Policy", "object-src 'none'"); |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.customizerbeanordering; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.ThrowingCustomizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; |
||||
import org.springframework.security.config.annotation.web.configurers.HttpsRedirectConfigurer; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class CustomizerBeanOrderingConfiguration { |
||||
|
||||
// tag::sample[]
|
||||
@Bean // <4>
|
||||
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((requests) -> requests |
||||
.anyRequest().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <2>
|
||||
ThrowingCustomizer<HttpSecurity> userAuthorization() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.authorizeHttpRequests((requests) -> requests |
||||
.requestMatchers("/users/**").hasRole("USER") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <1>
|
||||
ThrowingCustomizer<HttpSecurity> adminAuthorization() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.authorizeHttpRequests((requests) -> requests |
||||
.requestMatchers("/admins/**").hasRole("ADMIN") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// <3>
|
||||
|
||||
@Bean |
||||
Customizer<HeadersConfigurer<HttpSecurity>> contentSecurityPolicy() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
.policyDirectives("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
Customizer<HeadersConfigurer<HttpSecurity>> contentTypeOptions() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentTypeOptions(Customizer.withDefaults()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Bean |
||||
Customizer<HttpsRedirectConfigurer<HttpSecurity>> httpsRedirect() { |
||||
// @formatter:off
|
||||
return Customizer.withDefaults(); |
||||
// @formatter:on
|
||||
} |
||||
// end::sample[]
|
||||
|
||||
} |
||||
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.customizerbeanordering; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class CustomizerBeanOrderingTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this).mockMvcAfterSpringSecurityOk(); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
@Test |
||||
void authorizationOrdered() throws Exception { |
||||
this.spring.register( |
||||
CustomizerBeanOrderingConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.mockMvc |
||||
.perform(get("https://localhost/admins/1").with(user("admin").roles("ADMIN"))) |
||||
.andExpect(status().isOk()); |
||||
this.mockMvc |
||||
.perform(get("https://localhost/admins/1").with(user("user").roles("USER"))) |
||||
.andExpect(status().isForbidden()); |
||||
this.mockMvc |
||||
.perform(get("https://localhost/users/1").with(user("user").roles("USER"))) |
||||
.andExpect(status().isOk()); |
||||
this.mockMvc |
||||
.perform(get("https://localhost/users/1").with(user("user").roles("OTHER"))) |
||||
.andExpect(status().isForbidden()); |
||||
this.mockMvc |
||||
.perform(get("https://localhost/other").with(user("authenticated").roles("OTHER"))) |
||||
.andExpect(status().isOk()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.httpsecuritycustomizerbean; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.ThrowingCustomizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.ResultMatcher; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class HttpSecurityCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((requests) -> requests |
||||
.anyRequest().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// tag::httpSecurityCustomizer[]
|
||||
@Bean |
||||
ThrowingCustomizer<HttpSecurity> httpSecurityCustomizer() { |
||||
// @formatter:off
|
||||
return (http) -> http |
||||
.headers((headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
// <1>
|
||||
.policyDirectives("object-src 'none'") |
||||
) |
||||
) |
||||
// <2>
|
||||
.redirectToHttps(Customizer.withDefaults()); |
||||
// @formatter:on
|
||||
} |
||||
// end::httpSecurityCustomizer[]
|
||||
|
||||
} |
||||
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.httpsecuritycustomizerbean; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.ThrowingCustomizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.ResultMatcher; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class HttpSecurityCustomizerBeanTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
@Test |
||||
void httpSecurityCustomizer() throws Exception { |
||||
this.spring.register(HttpSecurityCustomizerBeanConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.mockMvc |
||||
.perform(get("/")) |
||||
.andExpect(redirectsToHttps()); |
||||
// headers are not sent back as a part of the redirect to https, so a separate request is necessary
|
||||
this.mockMvc.perform(get("https://localhost/")) |
||||
.andExpect(cspIsObjectSrcNone()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
private static @NotNull ResultMatcher redirectsToHttps() { |
||||
return mvcResult -> assertThat( |
||||
mvcResult.getResponse().getRedirectedUrl()).startsWith("https://"); |
||||
} |
||||
|
||||
private static @NotNull ResultMatcher cspIsObjectSrcNone() { |
||||
return header().string("Content-Security-Policy", "object-src 'none'"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.toplevelcustomizerbean; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.ThrowingCustomizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.ResultMatcher; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
public class TopLevelCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((requests) -> requests |
||||
.anyRequest().authenticated() |
||||
); |
||||
return http.build(); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
// tag::headersCustomizer[]
|
||||
@Bean |
||||
Customizer<HeadersConfigurer<HttpSecurity>> headersSecurity() { |
||||
// @formatter:off
|
||||
return (headers) -> headers |
||||
.contentSecurityPolicy((csp) -> csp |
||||
// <1>
|
||||
.policyDirectives("object-src 'none'") |
||||
); |
||||
// @formatter:on
|
||||
} |
||||
// end::headersCustomizer[]
|
||||
|
||||
} |
||||
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.docs.servlet.configuration.toplevelcustomizerbean; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.ThrowingCustomizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.ResultMatcher; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class TopLevelCustomizerBeanTests { |
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
|
||||
@Test |
||||
void headersCustomizer() throws Exception { |
||||
this.spring.register(TopLevelCustomizerBeanConfiguration.class).autowire(); |
||||
// @formatter:off
|
||||
this.mockMvc |
||||
.perform(get("/")) |
||||
.andExpect(cspIsObjectSrcNone()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
private static @NotNull ResultMatcher cspIsObjectSrcNone() { |
||||
return header().string("Content-Security-Policy", "object-src 'none'"); |
||||
} |
||||
} |
||||
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.reactive.configuration.customizerbeanordering |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.core.Ordered |
||||
import org.springframework.core.annotation.Order |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.ThrowingCustomizer |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.configurers.HttpsRedirectConfigurer |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers.anyExchange |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
internal class CustomizerBeanOrderingConfiguration { |
||||
// tag::sample[] |
||||
@Bean // <4> |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeExchange({ exchanges -> exchanges |
||||
.anyExchange().authenticated() |
||||
}) |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <2> |
||||
fun userAuthorization(): Customizer<ServerHttpSecurity> { |
||||
// @formatter:off |
||||
return Customizer { http -> http |
||||
.authorizeExchange { exchanges -> exchanges |
||||
.pathMatchers("/users/**").hasRole("USER") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <1> |
||||
fun adminAuthorization(): Customizer<ServerHttpSecurity> { |
||||
// @formatter:off |
||||
return ThrowingCustomizer { http -> http |
||||
.authorizeExchange { exchanges -> exchanges |
||||
.pathMatchers("/admins/**").hasRole("ADMIN") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
// <3> |
||||
|
||||
@Bean |
||||
fun contentSecurityPolicy(): Customizer<ServerHttpSecurity.HeaderSpec> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun contentTypeOptions(): Customizer<ServerHttpSecurity.HeaderSpec> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentTypeOptions(Customizer.withDefaults()) |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun httpsRedirect(): Customizer<ServerHttpSecurity.HttpsRedirectSpec> { |
||||
// @formatter:off |
||||
return Customizer.withDefaults() |
||||
// @formatter:on |
||||
} |
||||
// end::sample[] |
||||
} |
||||
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.reactive.configuration.customizerbeanordering |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class CustomizerBeanOrderingTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun authorizationOrdered() { |
||||
this.spring.register(CustomizerBeanOrderingConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
this.webTest.mutateWith(mockUser("admin").roles("ADMIN")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
this.webTest.mutateWith(mockUser("user").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden |
||||
this.webTest.mutateWith(mockUser("other").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/other") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.reactive.configuration.dslbeanordering |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.core.Ordered |
||||
import org.springframework.core.annotation.Order |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.* |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
internal class DslBeanOrderingConfiguration { |
||||
// tag::sample[] |
||||
// All of the Java Modular Configuration is applied first <1> |
||||
|
||||
@Bean // <5> |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
// @formatter:off |
||||
return http { |
||||
authorizeExchange { |
||||
authorize(anyExchange, authenticated) |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <3> |
||||
fun userAuthorization(): ServerHttpSecurityDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
authorizeExchange { |
||||
authorize("/users/**", hasRole("USER")) |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <2> |
||||
fun adminAuthorization(): ServerHttpSecurityDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
authorizeExchange { |
||||
authorize("/admins/**", hasRole("ADMIN")) |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
// <4> |
||||
|
||||
@Bean |
||||
fun contentSecurityPolicy(): ServerHeadersDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
contentSecurityPolicy { |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun contentTypeOptions(): ServerHeadersDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
contentTypeOptions { } |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun httpsRedirect(): ServerHttpsRedirectDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { } |
||||
// @formatter:on |
||||
} |
||||
// end::sample[] |
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.reactive.configuration.dslbeanordering |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.kt.docs.servlet.configuration.customizerbeanordering.CustomizerBeanOrderingConfiguration |
||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class DslBeanOrderingTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this).mockMvcAfterSpringSecurityOk() |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun dslOrdered() { |
||||
this.spring.register(org.springframework.security.kt.docs.reactive.configuration.customizerbeanordering.CustomizerBeanOrderingConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
this.webTest.mutateWith(mockUser("admin").roles("ADMIN")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/admins/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden |
||||
this.webTest.mutateWith(mockUser("user").roles("USER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
this.webTest.mutateWith(mockUser("user").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/users/1") |
||||
.exchange() |
||||
.expectStatus().isForbidden |
||||
this.webTest.mutateWith(mockUser("other").roles("OTHER")) |
||||
.get() |
||||
.uri("https://localhost/other") |
||||
.exchange() |
||||
.expectStatus().isOk |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.serverhttpsecuritycustomizerbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
|
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class ServerHttpSecurityCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeExchange({ exchanges -> exchanges |
||||
.anyExchange().authenticated() |
||||
}) |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
|
||||
// tag::httpSecurityCustomizer[] |
||||
@Bean |
||||
fun httpSecurityCustomizer(): Customizer<ServerHttpSecurity> { |
||||
// @formatter:off |
||||
return Customizer { http -> http |
||||
.headers { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
// <1> |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// <2> |
||||
.redirectToHttps(Customizer.withDefaults()) |
||||
} |
||||
// @formatter:on |
||||
} |
||||
// end::httpSecurityCustomizer[] |
||||
|
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.serverhttpsecuritycustomizerbean |
||||
|
||||
import org.assertj.core.api.Assertions |
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import java.util.function.Consumer |
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class ServerHttpSecurityCustomizerBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun `serverhttpsecurity customizer config`() { |
||||
this.spring.register(ServerHttpSecurityCustomizerBeanConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader().location("https://localhost/") |
||||
.expectHeader() |
||||
.value("Content-Security-Policy", Consumer { csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
}) |
||||
// @formatter:on |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.serverhttpsecuritydslbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity |
||||
import org.springframework.security.config.web.server.ServerHttpSecurityDsl |
||||
import org.springframework.security.config.web.server.invoke |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class ServerHttpSecurityDslBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
return http { |
||||
authorizeExchange { |
||||
authorize(anyExchange, authenticated) |
||||
} |
||||
} |
||||
} |
||||
|
||||
// tag::httpSecurityDslBean[] |
||||
@Bean |
||||
fun httpSecurityDslBean(): ServerHttpSecurityDsl.() -> Unit { |
||||
return { |
||||
headers { |
||||
contentSecurityPolicy { |
||||
// <1> |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
// <2> |
||||
redirectToHttps { } |
||||
} |
||||
} |
||||
// end::httpSecurityDslBean[] |
||||
|
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.serverhttpsecuritydslbean |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
import java.util.function.Consumer |
||||
|
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class ServerHttpSecurityDslBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun `ServerHttpSecurityDslBean`() { |
||||
this.spring.register(ServerHttpSecurityDslBeanConfiguration::class.java).autowire() |
||||
|
||||
// @formatter:off |
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader().location("https://localhost/") |
||||
.expectHeader().value("Content-Security-Policy", Consumer { csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
}) |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.toplevelcustomizerbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
|
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class TopLevelCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeExchange({ exchanges -> exchanges |
||||
.anyExchange().authenticated() |
||||
}) |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
// tag::headersCustomizer[] |
||||
@Bean |
||||
fun headersSecurity(): Customizer<ServerHttpSecurity.HeaderSpec> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
// <1> |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
// end::headersCustomizer[] |
||||
|
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.toplevelcustomizerbean |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import java.util.function.Consumer |
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class TopLevelCustomizerBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun `top level dsl bean`() { |
||||
this.spring.register(TopLevelCustomizerBeanConfiguration::class.java).autowire() |
||||
|
||||
// @formatter:off |
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader().value("Content-Security-Policy", Consumer { csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
}) |
||||
// @formatter:on |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.topleveldslbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity |
||||
import org.springframework.security.config.web.server.ServerHeadersDsl |
||||
import org.springframework.security.config.web.server.ServerHttpSecurity |
||||
import org.springframework.security.config.web.server.invoke |
||||
import org.springframework.security.web.server.SecurityWebFilterChain |
||||
|
||||
|
||||
@EnableWebFluxSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class TopLevelDslBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { |
||||
return http { |
||||
authorizeExchange { |
||||
authorize(anyExchange, authenticated) |
||||
} |
||||
} |
||||
} |
||||
|
||||
// tag::headersSecurity[] |
||||
@Bean |
||||
fun headersSecurity(): ServerHeadersDsl.() -> Unit { |
||||
return { |
||||
contentSecurityPolicy { |
||||
// <1> |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
} |
||||
// end::headersSecurity[] |
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
package org.springframework.security.kt.docs.reactive.configuration.topleveldslbean |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.reactive.server.WebTestClient |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
import java.util.function.Consumer |
||||
|
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class TopLevelDslBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var webTest: WebTestClient |
||||
|
||||
@Test |
||||
fun `HttpSecurityDslBean`() { |
||||
this.spring.register(TopLevelDslBeanConfiguration::class.java).autowire() |
||||
|
||||
// @formatter:off |
||||
this.webTest |
||||
.get() |
||||
.uri("http://localhost/") |
||||
.exchange() |
||||
.expectHeader().value("Content-Security-Policy", Consumer { csp -> |
||||
assertThat(csp).isEqualTo("object-src 'none'") |
||||
}) |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.servlet.configuration.customizerbeanordering |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.core.Ordered |
||||
import org.springframework.core.annotation.Order |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.ThrowingCustomizer |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.configurers.HttpsRedirectConfigurer |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
internal class CustomizerBeanOrderingConfiguration { |
||||
// tag::sample[] |
||||
@Bean // <4> |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeHttpRequests({ requests -> requests |
||||
.anyRequest().authenticated() |
||||
}) |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <2> |
||||
fun userAuthorization(): ThrowingCustomizer<HttpSecurity> { |
||||
// @formatter:off |
||||
return ThrowingCustomizer { http -> http |
||||
.authorizeHttpRequests { requests -> requests |
||||
.requestMatchers("/users/**").hasRole("USER") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <1> |
||||
fun adminAuthorization(): ThrowingCustomizer<HttpSecurity> { |
||||
// @formatter:off |
||||
return ThrowingCustomizer { http -> http |
||||
.authorizeHttpRequests { requests -> requests |
||||
.requestMatchers("/admins/**").hasRole("ADMIN") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
// <3> |
||||
|
||||
@Bean |
||||
fun contentSecurityPolicy(): Customizer<HeadersConfigurer<HttpSecurity>> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun contentTypeOptions(): Customizer<HeadersConfigurer<HttpSecurity>> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentTypeOptions(Customizer.withDefaults()) |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun httpsRedirect(): Customizer<HttpsRedirectConfigurer<HttpSecurity>> { |
||||
// @formatter:off |
||||
return Customizer.withDefaults<HttpsRedirectConfigurer<HttpSecurity>>() |
||||
// @formatter:on |
||||
} |
||||
// end::sample[] |
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.servlet.configuration.customizerbeanordering |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class CustomizerBeanOrderingTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this).mockMvcAfterSpringSecurityOk() |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun authorizationOrdered() { |
||||
this.spring.register(CustomizerBeanOrderingConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
this.mockMvc.get("https://localhost/admins/1") { |
||||
with(user("admin").roles("ADMIN")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
this.mockMvc.get("https://localhost/admins/1") { |
||||
with(user("user").roles("USER")) |
||||
}.andExpect { |
||||
status { isForbidden() } |
||||
} |
||||
this.mockMvc.get("https://localhost/users/1") { |
||||
with(user("user").roles("USER")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
this.mockMvc.get("https://localhost/users/1") { |
||||
with(user("noUserRole").roles("OTHER")) |
||||
}.andExpect { |
||||
status { isForbidden() } |
||||
} |
||||
this.mockMvc.get("https://localhost/other") { |
||||
with(user("authenticated").roles("OTHER")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.servlet.configuration.dslbeanordering |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.core.Ordered |
||||
import org.springframework.core.annotation.Order |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.ThrowingCustomizer |
||||
import org.springframework.security.config.annotation.web.HeadersDsl |
||||
import org.springframework.security.config.annotation.web.HttpSecurityDsl |
||||
import org.springframework.security.config.annotation.web.HttpsRedirectDsl |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.configurers.HttpsRedirectConfigurer |
||||
import org.springframework.security.config.annotation.web.invoke |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
internal class DslBeanOrderingConfiguration { |
||||
// tag::sample[] |
||||
// All of the Java Modular Configuration is applied first <1> |
||||
|
||||
@Bean // <5> |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http { |
||||
authorizeHttpRequests { |
||||
authorize(anyRequest, authenticated) |
||||
} |
||||
} |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.LOWEST_PRECEDENCE) // <3> |
||||
fun userAuthorization(): HttpSecurityDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
authorizeHttpRequests { |
||||
authorize("/users/**", hasRole("USER")) |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) // <2> |
||||
fun adminAuthorization(): HttpSecurityDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
authorizeHttpRequests { |
||||
authorize("/admins/**", hasRole("ADMIN")) |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
// <4> |
||||
|
||||
@Bean |
||||
fun contentSecurityPolicy(): HeadersDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
contentSecurityPolicy { |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun contentTypeOptions(): HeadersDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { |
||||
contentTypeOptions { } |
||||
} |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Bean |
||||
fun httpsRedirect(): HttpsRedirectDsl.() -> Unit { |
||||
// @formatter:off |
||||
return { } |
||||
// @formatter:on |
||||
} |
||||
// end::sample[] |
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
/* |
||||
* Copyright 2004-present 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 |
||||
* |
||||
* https://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.kt.docs.servlet.configuration.dslbeanordering |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.kt.docs.servlet.configuration.customizerbeanordering.CustomizerBeanOrderingConfiguration |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class DslBeanOrderingTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this).mockMvcAfterSpringSecurityOk() |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun dslOrdered() { |
||||
this.spring.register(DslBeanOrderingConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
this.mockMvc.get("https://localhost/admins/1") { |
||||
with(user("admin").roles("ADMIN")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
this.mockMvc.get("https://localhost/admins/1") { |
||||
with(user("user").roles("USER")) |
||||
}.andExpect { |
||||
status { isForbidden() } |
||||
} |
||||
this.mockMvc.get("https://localhost/users/1") { |
||||
with(user("user").roles("USER")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
this.mockMvc.get("https://localhost/users/1") { |
||||
with(user("noUserRole").roles("OTHER")) |
||||
}.andExpect { |
||||
status { isForbidden() } |
||||
} |
||||
this.mockMvc.get("https://localhost/other") { |
||||
with(user("authenticated").roles("OTHER")) |
||||
}.andExpect { |
||||
status { isOk() } |
||||
} |
||||
// @formatter:on |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.httpsecuritycustomizerbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.ThrowingCustomizer |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.invoke |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
|
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class HttpSecurityCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
http { |
||||
authorizeHttpRequests { |
||||
authorize(anyRequest, authenticated) |
||||
} |
||||
} |
||||
return http.build() |
||||
} |
||||
|
||||
|
||||
// tag::httpSecurityCustomizer[] |
||||
@Bean |
||||
fun httpSecurityCustomizer(): ThrowingCustomizer<HttpSecurity> { |
||||
// @formatter:off |
||||
return ThrowingCustomizer { http -> http |
||||
.headers { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
// <1> |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// <2> |
||||
.redirectToHttps(Customizer.withDefaults()) |
||||
} |
||||
// @formatter:on |
||||
} |
||||
// end::httpSecurityCustomizer[] |
||||
|
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.httpsecuritycustomizerbean |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class HttpSecurityCustomizerBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun `httpsecurity customizer config`() { |
||||
this.spring.register(HttpSecurityCustomizerBeanConfiguration::class.java).autowire() |
||||
|
||||
this.mockMvc.get("/") |
||||
.andExpect { |
||||
redirectedUrl("https://localhost/") |
||||
} |
||||
this.mockMvc.get("https://localhost/") |
||||
.andExpect { |
||||
header { |
||||
string("Content-Security-Policy", "object-src 'none'") |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.httpsecuritydslbean |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.annotation.web.HeadersDsl |
||||
import org.springframework.security.config.annotation.web.HttpSecurityDsl |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.invoke |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class HttpSecurityDslBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
http { |
||||
authorizeHttpRequests { |
||||
authorize(anyRequest, authenticated) |
||||
} |
||||
} |
||||
return http.build() |
||||
} |
||||
|
||||
// tag::httpSecurityDslBean[] |
||||
@Bean |
||||
fun httpSecurityDslBean(): HttpSecurityDsl.() -> Unit { |
||||
return { |
||||
headers { |
||||
contentSecurityPolicy { |
||||
// <1> |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
// <2> |
||||
redirectToHttps { } |
||||
} |
||||
} |
||||
// end::httpSecurityDslBean[] |
||||
|
||||
} |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.httpsecuritydslbean |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class HttpSecurityDslBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun `HttpSecurityDslBean`() { |
||||
this.spring.register(HttpSecurityDslBeanConfiguration::class.java).autowire() |
||||
|
||||
this.mockMvc.get("/") |
||||
.andExpect { |
||||
redirectedUrl("https://localhost/") |
||||
} |
||||
|
||||
this.mockMvc.get("https://localhost/") |
||||
.andExpect { |
||||
header { |
||||
string("Content-Security-Policy", "object-src 'none'") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.toplevelcustomizerbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.Customizer |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer |
||||
import org.springframework.security.config.annotation.web.invoke |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
|
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class TopLevelCustomizerBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http { |
||||
authorizeHttpRequests { |
||||
authorize(anyRequest, authenticated) |
||||
} |
||||
} |
||||
return http.build() |
||||
// @formatter:on |
||||
} |
||||
|
||||
// tag::headersCustomizer[] |
||||
@Bean |
||||
fun headersSecurity(): Customizer<HeadersConfigurer<HttpSecurity>> { |
||||
// @formatter:off |
||||
return Customizer { headers -> headers |
||||
.contentSecurityPolicy { csp -> csp |
||||
// <1> |
||||
.policyDirectives("object-src 'none'") |
||||
} |
||||
} |
||||
// @formatter:on |
||||
} |
||||
// end::headersCustomizer[] |
||||
|
||||
} |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.toplevelcustomizerbean |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class TopLevelCustomizerBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun `top level dsl bean`() { |
||||
this.spring.register(TopLevelCustomizerBeanConfiguration::class.java).autowire() |
||||
|
||||
this.mockMvc.get("/") |
||||
.andExpect { |
||||
header { |
||||
string("Content-Security-Policy", "object-src 'none'") |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.topleveldslbean |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.config.annotation.web.HeadersDsl |
||||
import org.springframework.security.config.annotation.web.HttpSecurityDsl |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.invoke |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration(proxyBeanMethods = false) |
||||
class TopLevelDslBeanConfiguration { |
||||
|
||||
@Bean |
||||
fun springSecurity(http: HttpSecurity): SecurityFilterChain { |
||||
http { |
||||
authorizeHttpRequests { |
||||
authorize(anyRequest, authenticated) |
||||
} |
||||
} |
||||
return http.build() |
||||
} |
||||
|
||||
// tag::headersSecurity[] |
||||
@Bean |
||||
fun headersSecurity(): HeadersDsl.() -> Unit { |
||||
return { |
||||
contentSecurityPolicy { |
||||
// <1> |
||||
policyDirectives = "object-src 'none'" |
||||
} |
||||
} |
||||
} |
||||
// end::headersSecurity[] |
||||
} |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
package org.springframework.security.kt.docs.servlet.configuration.topleveldslbean |
||||
|
||||
import org.junit.jupiter.api.Test |
||||
import org.junit.jupiter.api.extension.ExtendWith |
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.get |
||||
|
||||
|
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class TopLevelDslBeanTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
fun `HttpSecurityDslBean`() { |
||||
this.spring.register(TopLevelDslBeanConfiguration::class.java).autowire() |
||||
|
||||
this.mockMvc.get("/") |
||||
.andExpect { |
||||
header { |
||||
string("Content-Security-Policy", "object-src 'none'") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue