Browse Source
Signed-off-by: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com>pull/17865/head
37 changed files with 2718 additions and 177 deletions
@ -0,0 +1,124 @@
@@ -0,0 +1,124 @@
|
||||
/* |
||||
* Copyright 2002-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.authorization; |
||||
|
||||
import org.jspecify.annotations.Nullable; |
||||
|
||||
/** |
||||
* A factory for creating different kinds of {@link AuthorizationManager} instances. |
||||
* |
||||
* @param <T> the type of object that the authorization check is being done on |
||||
* @author Steve Riesenberg |
||||
* @since 7.0 |
||||
*/ |
||||
public interface AuthorizationManagerFactory<T extends @Nullable Object> { |
||||
|
||||
/** |
||||
* Create an {@link AuthorizationManager} that allows anyone. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> permitAll() { |
||||
return SingleResultAuthorizationManager.permitAll(); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that does not allow anyone. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> denyAll() { |
||||
return SingleResultAuthorizationManager.denyAll(); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that requires users to have the specified |
||||
* role. |
||||
* @param role the role (automatically prepended with ROLE_) that should be required |
||||
* to allow access (i.e. USER, ADMIN, etc.) |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> hasRole(String role) { |
||||
return AuthorityAuthorizationManager.hasRole(role); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that requires users to have one of many |
||||
* roles. |
||||
* @param roles the roles (automatically prepended with ROLE_) that the user should |
||||
* have at least one of to allow access (i.e. USER, ADMIN, etc.) |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> hasAnyRole(String... roles) { |
||||
return AuthorityAuthorizationManager.hasAnyRole(roles); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that requires users to have the specified |
||||
* authority. |
||||
* @param authority the authority that should be required to allow access (i.e. |
||||
* ROLE_USER, ROLE_ADMIN, etc.) |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> hasAuthority(String authority) { |
||||
return AuthorityAuthorizationManager.hasAuthority(authority); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that requires users to have one of many |
||||
* authorities. |
||||
* @param authorities the authorities that the user should have at least one of to |
||||
* allow access (i.e. ROLE_USER, ROLE_ADMIN, etc.) |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> hasAnyAuthority(String... authorities) { |
||||
return AuthorityAuthorizationManager.hasAnyAuthority(authorities); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that allows any authenticated user. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> authenticated() { |
||||
return AuthenticatedAuthorizationManager.authenticated(); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that allows users who have authenticated |
||||
* and were not remembered. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> fullyAuthenticated() { |
||||
return AuthenticatedAuthorizationManager.fullyAuthenticated(); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that allows users that have been |
||||
* remembered. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> rememberMe() { |
||||
return AuthenticatedAuthorizationManager.rememberMe(); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link AuthorizationManager} that allows only anonymous users. |
||||
* @return A new {@link AuthorizationManager} instance |
||||
*/ |
||||
default AuthorizationManager<T> anonymous() { |
||||
return AuthenticatedAuthorizationManager.anonymous(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/* |
||||
* Copyright 2002-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.authorization; |
||||
|
||||
import org.jspecify.annotations.Nullable; |
||||
|
||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; |
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy; |
||||
import org.springframework.security.authentication.AuthenticationTrustResolver; |
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* A factory for creating different kinds of {@link AuthorizationManager} instances. |
||||
* |
||||
* @param <T> the type of object that the authorization check is being done on |
||||
* @author Steve Riesenberg |
||||
* @since 7.0 |
||||
*/ |
||||
public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object> |
||||
implements AuthorizationManagerFactory<T> { |
||||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); |
||||
|
||||
private RoleHierarchy roleHierarchy = new NullRoleHierarchy(); |
||||
|
||||
private String rolePrefix = "ROLE_"; |
||||
|
||||
/** |
||||
* Sets the {@link AuthenticationTrustResolver} used to check the user's |
||||
* authentication. |
||||
* @param trustResolver the {@link AuthenticationTrustResolver} to use |
||||
*/ |
||||
public void setTrustResolver(AuthenticationTrustResolver trustResolver) { |
||||
Assert.notNull(trustResolver, "trustResolver cannot be null"); |
||||
this.trustResolver = trustResolver; |
||||
} |
||||
|
||||
/** |
||||
* Sets the {@link RoleHierarchy} used to discover reachable authorities. |
||||
* @param roleHierarchy the {@link RoleHierarchy} to use |
||||
*/ |
||||
public void setRoleHierarchy(RoleHierarchy roleHierarchy) { |
||||
Assert.notNull(roleHierarchy, "roleHierarchy cannot be null"); |
||||
this.roleHierarchy = roleHierarchy; |
||||
} |
||||
|
||||
/** |
||||
* Sets the prefix used to create an authority name from a role name. Can be an empty |
||||
* string. |
||||
* @param rolePrefix the role prefix to use |
||||
*/ |
||||
public void setRolePrefix(String rolePrefix) { |
||||
Assert.notNull(rolePrefix, "rolePrefix cannot be null"); |
||||
this.rolePrefix = rolePrefix; |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> hasRole(String role) { |
||||
return hasAnyRole(role); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> hasAnyRole(String... roles) { |
||||
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles)); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> hasAuthority(String authority) { |
||||
return withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> hasAnyAuthority(String... authorities) { |
||||
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> authenticated() { |
||||
return withTrustResolver(AuthenticatedAuthorizationManager.authenticated()); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> fullyAuthenticated() { |
||||
return withTrustResolver(AuthenticatedAuthorizationManager.fullyAuthenticated()); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> rememberMe() { |
||||
return withTrustResolver(AuthenticatedAuthorizationManager.rememberMe()); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<T> anonymous() { |
||||
return withTrustResolver(AuthenticatedAuthorizationManager.anonymous()); |
||||
} |
||||
|
||||
private AuthorityAuthorizationManager<T> withRoleHierarchy(AuthorityAuthorizationManager<T> authorizationManager) { |
||||
authorizationManager.setRoleHierarchy(this.roleHierarchy); |
||||
return authorizationManager; |
||||
} |
||||
|
||||
private AuthenticatedAuthorizationManager<T> withTrustResolver( |
||||
AuthenticatedAuthorizationManager<T> authorizationManager) { |
||||
authorizationManager.setTrustResolver(this.trustResolver); |
||||
return authorizationManager; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
|
||||
/* |
||||
* Copyright 2002-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.authorization; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link AuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
public class AuthorizationManagerFactoryTests { |
||||
|
||||
@Test |
||||
public void permitAllReturnsSingleResultAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.permitAll(); |
||||
assertThat(authorizationManager).isInstanceOf(SingleResultAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void denyAllReturnsSingleResultAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.denyAll(); |
||||
assertThat(authorizationManager).isInstanceOf(SingleResultAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void hasRoleReturnsAuthorityAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.hasRole("USER"); |
||||
assertThat(authorizationManager).isInstanceOf(AuthorityAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void hasAnyRoleReturnsAuthorityAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.hasAnyRole("USER", "ADMIN"); |
||||
assertThat(authorizationManager).isInstanceOf(AuthorityAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void hasAuthorityReturnsAuthorityAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.hasAuthority("authority1"); |
||||
assertThat(authorizationManager).isInstanceOf(AuthorityAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void hasAnyAuthorityReturnsAuthorityAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.hasAnyAuthority("authority1", "authority2"); |
||||
assertThat(authorizationManager).isInstanceOf(AuthorityAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void authenticatedReturnsAuthenticatedAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.authenticated(); |
||||
assertThat(authorizationManager).isInstanceOf(AuthenticatedAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void fullyAuthenticatedReturnsAuthenticatedAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.fullyAuthenticated(); |
||||
assertThat(authorizationManager).isInstanceOf(AuthenticatedAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void rememberMeReturnsAuthenticatedAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.rememberMe(); |
||||
assertThat(authorizationManager).isInstanceOf(AuthenticatedAuthorizationManager.class); |
||||
} |
||||
|
||||
@Test |
||||
public void anonymousReturnsAuthenticatedAuthorizationManagerByDefault() { |
||||
AuthorizationManagerFactory<String> factory = new DefaultAuthorizationManagerFactory<>(); |
||||
AuthorizationManager<String> authorizationManager = factory.anonymous(); |
||||
assertThat(authorizationManager).isInstanceOf(AuthenticatedAuthorizationManager.class); |
||||
} |
||||
|
||||
} |
||||
@ -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 clients 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.authorization.authzauthorizationmanagerfactory; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; |
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl; |
||||
import org.springframework.security.authentication.TestingAuthenticationToken; |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory; |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory; |
||||
|
||||
/** |
||||
* Documentation for {@link AuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
public class AuthorizationManagerFactoryConfiguration { |
||||
|
||||
// tag::config[]
|
||||
@Bean |
||||
<T> AuthorizationManagerFactory<T> authorizationManagerFactory() { |
||||
DefaultAuthorizationManagerFactory<T> authorizationManagerFactory = |
||||
new DefaultAuthorizationManagerFactory<>(); |
||||
authorizationManagerFactory.setTrustResolver(getAuthenticationTrustResolver()); |
||||
authorizationManagerFactory.setRoleHierarchy(getRoleHierarchy()); |
||||
authorizationManagerFactory.setRolePrefix("role_"); |
||||
|
||||
return authorizationManagerFactory; |
||||
} |
||||
// end::config[]
|
||||
|
||||
private static AuthenticationTrustResolverImpl getAuthenticationTrustResolver() { |
||||
AuthenticationTrustResolverImpl authenticationTrustResolver = |
||||
new AuthenticationTrustResolverImpl(); |
||||
authenticationTrustResolver.setAnonymousClass(Anonymous.class); |
||||
authenticationTrustResolver.setRememberMeClass(RememberMe.class); |
||||
|
||||
return authenticationTrustResolver; |
||||
} |
||||
|
||||
private static RoleHierarchyImpl getRoleHierarchy() { |
||||
return RoleHierarchyImpl.fromHierarchy("role_admin > role_user"); |
||||
} |
||||
|
||||
static class Anonymous extends TestingAuthenticationToken { |
||||
|
||||
Anonymous(String principal) { |
||||
super(principal, "", "role_anonymous"); |
||||
} |
||||
|
||||
} |
||||
|
||||
static class RememberMe extends TestingAuthenticationToken { |
||||
|
||||
RememberMe(String principal) { |
||||
super(principal, "", "role_rememberMe"); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,208 @@
@@ -0,0 +1,208 @@
|
||||
/* |
||||
* 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 clients 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.authorization.authzauthorizationmanagerfactory; |
||||
|
||||
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.http.HttpStatus; |
||||
import org.springframework.security.access.prepost.PreAuthorize; |
||||
import org.springframework.security.authentication.TestingAuthenticationToken; |
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.Anonymous; |
||||
import org.springframework.security.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.RememberMe; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
/** |
||||
* Tests for {@link AuthorizationManagerFactoryConfiguration}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class AuthorizationManagerFactoryConfigurationTests { |
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
MockMvc mockMvc; |
||||
|
||||
@Test |
||||
void getAnonymousWhenCustomAnonymousClassThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new Anonymous("anonymous"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/anonymous").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getAnonymousWhenAuthenticatedThenForbidden() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/anonymous").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getRememberMeWhenCustomRememberMeClassThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new RememberMe("rememberMe"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/rememberMe").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getRememberMeWhenAuthenticatedThenForbidden() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/rememberMe").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenCustomUserRoleThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenCustomAdminRoleThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "role_admin"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getPreAuthorizeWhenCustomUserRoleThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getPreAuthorizeWhenCustomAdminRoleThenOk() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "role_admin"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getPreAuthorizeWhenOtherRoleThenForbidden() throws Exception { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class, |
||||
TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("other", "", "role_other"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@EnableMethodSecurity |
||||
@Configuration |
||||
static class SecurityConfiguration { |
||||
|
||||
@Bean |
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((authorize) -> authorize |
||||
.requestMatchers("/anonymous").anonymous() |
||||
.requestMatchers("/rememberMe").rememberMe() |
||||
.requestMatchers("/user").hasRole("user") |
||||
.requestMatchers("/preAuthorize").permitAll() |
||||
.anyRequest().denyAll() |
||||
); |
||||
// @formatter:on
|
||||
return http.build(); |
||||
} |
||||
|
||||
} |
||||
|
||||
@RestController |
||||
static class TestController { |
||||
|
||||
@GetMapping({ "/anonymous", "/rememberMe", "/user" }) |
||||
@ResponseStatus(HttpStatus.OK) |
||||
void httpRequest() { |
||||
} |
||||
|
||||
@GetMapping("/preAuthorize") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PreAuthorize("hasRole('user')") |
||||
void preAuthorize() { |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* 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 clients 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.authorization.customizingauthorizationmanagers; |
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager; |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory; |
||||
import org.springframework.security.authorization.AuthorizationManagers; |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory; |
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* Documentation for {@link AuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
// tag::class[]
|
||||
@Component |
||||
public class CustomHttpRequestsAuthorizationManagerFactory |
||||
implements AuthorizationManagerFactory<RequestAuthorizationContext> { |
||||
|
||||
private final AuthorizationManagerFactory<RequestAuthorizationContext> delegate = |
||||
new DefaultAuthorizationManagerFactory<>(); |
||||
|
||||
@Override |
||||
public AuthorizationManager<RequestAuthorizationContext> authenticated() { |
||||
return AuthorizationManagers.allOf( |
||||
this.delegate.authenticated(), |
||||
this.delegate.hasRole("USER") |
||||
); |
||||
} |
||||
|
||||
} |
||||
// end::class[]
|
||||
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
/* |
||||
* 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 clients 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.authorization.customizingauthorizationmanagers; |
||||
|
||||
import java.util.Collections; |
||||
|
||||
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.http.HttpStatus; |
||||
import org.springframework.security.authentication.TestingAuthenticationToken; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous; |
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
/** |
||||
* Tests for {@link CustomHttpRequestsAuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class CustomHttpRequestsAuthorizationManagerFactoryTests { |
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
MockMvc mockMvc; |
||||
|
||||
@Test |
||||
void getHelloWhenAnonymousThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(anonymous())) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(unauthenticated()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getHelloWhenAuthenticatedWithNoRolesThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", Collections.emptyList()); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getHelloWhenAuthenticatedWithUserRoleThenOk() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_USER"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getHelloWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration |
||||
static class SecurityConfiguration { |
||||
|
||||
@Bean |
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((authorize) -> authorize |
||||
.anyRequest().authenticated() |
||||
); |
||||
// @formatter:on
|
||||
return http.build(); |
||||
} |
||||
|
||||
@Bean |
||||
CustomHttpRequestsAuthorizationManagerFactory customHttpRequestsAuthorizationManagerFactory() { |
||||
return new CustomHttpRequestsAuthorizationManagerFactory(); |
||||
} |
||||
|
||||
} |
||||
|
||||
@RestController |
||||
static class TestController { |
||||
|
||||
@GetMapping("/**") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
void ok() { |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
/* |
||||
* 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 clients 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.authorization.customizingauthorizationmanagers; |
||||
|
||||
import org.aopalliance.intercept.MethodInvocation; |
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager; |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory; |
||||
import org.springframework.security.authorization.AuthorizationManagers; |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* Documentation for {@link AuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
// tag::class[]
|
||||
@Component |
||||
public class CustomMethodInvocationAuthorizationManagerFactory |
||||
implements AuthorizationManagerFactory<MethodInvocation> { |
||||
|
||||
private final AuthorizationManagerFactory<MethodInvocation> delegate = |
||||
new DefaultAuthorizationManagerFactory<>(); |
||||
|
||||
@Override |
||||
public AuthorizationManager<MethodInvocation> hasRole(String role) { |
||||
return AuthorizationManagers.anyOf( |
||||
this.delegate.hasRole(role), |
||||
this.delegate.hasRole("ADMIN") |
||||
); |
||||
} |
||||
|
||||
@Override |
||||
public AuthorizationManager<MethodInvocation> hasAnyRole(String... roles) { |
||||
return AuthorizationManagers.anyOf( |
||||
this.delegate.hasAnyRole(roles), |
||||
this.delegate.hasRole("ADMIN") |
||||
); |
||||
} |
||||
|
||||
} |
||||
// end::class[]
|
||||
@ -0,0 +1,191 @@
@@ -0,0 +1,191 @@
|
||||
/* |
||||
* 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 clients 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.authorization.customizingauthorizationmanagers; |
||||
|
||||
import java.util.Collections; |
||||
|
||||
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.http.HttpStatus; |
||||
import org.springframework.security.access.prepost.PreAuthorize; |
||||
import org.springframework.security.authentication.TestingAuthenticationToken; |
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.test.SpringTestContext; |
||||
import org.springframework.security.config.test.SpringTestContextExtension; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous; |
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
/** |
||||
* Tests for {@link CustomMethodInvocationAuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension.class) |
||||
public class CustomMethodInvocationAuthorizationManagerFactoryTests { |
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this); |
||||
|
||||
@Autowired |
||||
MockMvc mockMvc; |
||||
|
||||
@Test |
||||
void getUserWhenAnonymousThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(anonymous())) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(unauthenticated()); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenAuthenticatedWithNoRolesThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", Collections.emptyList()); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenAuthenticatedWithUserRoleThenOk() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_USER"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenAuthenticatedWithAdminRoleThenOk() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "ROLE_ADMIN"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getUserWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getRolesWhenAuthenticatedWithRole1RoleThenOk() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_ROLE1"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getRolesWhenAuthenticatedWithAdminRoleThenOk() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "ROLE_ADMIN"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@Test |
||||
void getRolesWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception { |
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire(); |
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER"); |
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)); |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@EnableMethodSecurity |
||||
@Configuration |
||||
static class SecurityConfiguration { |
||||
|
||||
@Bean |
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((authorize) -> authorize |
||||
.anyRequest().authenticated() |
||||
); |
||||
// @formatter:on
|
||||
return http.build(); |
||||
} |
||||
|
||||
@Bean |
||||
CustomMethodInvocationAuthorizationManagerFactory customMethodInvocationAuthorizationManagerFactory() { |
||||
return new CustomMethodInvocationAuthorizationManagerFactory(); |
||||
} |
||||
|
||||
} |
||||
|
||||
@RestController |
||||
static class TestController { |
||||
|
||||
@GetMapping("/user") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PreAuthorize("hasRole('USER')") |
||||
void user() { |
||||
} |
||||
|
||||
@GetMapping("/roles") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@PreAuthorize("hasAnyRole('ROLE1', 'ROLE2')") |
||||
void roles() { |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* 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.authorization.authzauthorizationmanagerfactory |
||||
|
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl |
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl |
||||
import org.springframework.security.authentication.TestingAuthenticationToken |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory |
||||
|
||||
/** |
||||
* Documentation for [org.springframework.security.authorization.AuthorizationManagerFactory]. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
class AuthorizationManagerFactoryConfiguration { |
||||
// tag::config[] |
||||
@Bean |
||||
fun <T> authorizationManagerFactory(): AuthorizationManagerFactory<T> { |
||||
val authorizationManagerFactory = DefaultAuthorizationManagerFactory<T>() |
||||
authorizationManagerFactory.setTrustResolver(getAuthenticationTrustResolver()) |
||||
authorizationManagerFactory.setRoleHierarchy(getRoleHierarchy()) |
||||
authorizationManagerFactory.setRolePrefix("role_") |
||||
|
||||
return authorizationManagerFactory |
||||
} |
||||
// end::config[] |
||||
|
||||
private fun getAuthenticationTrustResolver(): AuthenticationTrustResolverImpl { |
||||
val authenticationTrustResolver = AuthenticationTrustResolverImpl() |
||||
authenticationTrustResolver.setAnonymousClass(Anonymous::class.java) |
||||
authenticationTrustResolver.setRememberMeClass(RememberMe::class.java) |
||||
|
||||
return authenticationTrustResolver |
||||
} |
||||
|
||||
private fun getRoleHierarchy(): RoleHierarchyImpl { |
||||
return RoleHierarchyImpl.fromHierarchy("role_admin > role_user") |
||||
} |
||||
|
||||
internal class Anonymous(principal: String) : |
||||
TestingAuthenticationToken(principal, "", "role_anonymous") |
||||
|
||||
internal class RememberMe(principal: String) : |
||||
TestingAuthenticationToken(principal, "", "role_rememberMe") |
||||
} |
||||
@ -0,0 +1,229 @@
@@ -0,0 +1,229 @@
|
||||
/* |
||||
* 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.authorization.authzauthorizationmanagerfactory |
||||
|
||||
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.http.HttpStatus |
||||
import org.springframework.security.access.prepost.PreAuthorize |
||||
import org.springframework.security.authentication.TestingAuthenticationToken |
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.kt.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.Anonymous |
||||
import org.springframework.security.kt.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.RememberMe |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication |
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status |
||||
import org.springframework.web.bind.annotation.GetMapping |
||||
import org.springframework.web.bind.annotation.ResponseStatus |
||||
import org.springframework.web.bind.annotation.RestController |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
/** |
||||
* Tests for [AuthorizationManagerFactoryConfiguration]. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class AuthorizationManagerFactoryConfigurationTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getAnonymousWhenCustomAnonymousClassThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = Anonymous("anonymous") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/anonymous").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getAnonymousWhenAuthenticatedThenForbidden() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "role_user") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/anonymous").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getRememberMeWhenCustomRememberMeClassThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = RememberMe("rememberMe") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/rememberMe").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getRememberMeWhenAuthenticatedThenForbidden() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val user = TestingAuthenticationToken("user", "", "role_user") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/rememberMe").with(authentication(user))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(user)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenCustomUserRoleThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "role_user") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenCustomAdminRoleThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val admin = TestingAuthenticationToken("admin", "", "role_admin") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(admin))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(admin)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getPreAuthorizeWhenCustomUserRoleThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "role_user") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getPreAuthorizeWhenCustomAdminRoleThenOk() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = TestingAuthenticationToken("admin", "", "role_admin") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getPreAuthorizeWhenOtherRoleThenForbidden() { |
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java) |
||||
.autowire() |
||||
val authentication = TestingAuthenticationToken("other", "", "role_other") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@EnableMethodSecurity |
||||
@Configuration |
||||
internal open class SecurityConfiguration { |
||||
@Bean |
||||
@Throws(Exception::class) |
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http.authorizeHttpRequests { authorize -> |
||||
authorize |
||||
.requestMatchers("/anonymous").anonymous() |
||||
.requestMatchers("/rememberMe").rememberMe() |
||||
.requestMatchers("/user").hasRole("user") |
||||
.requestMatchers("/preAuthorize").permitAll() |
||||
.anyRequest().denyAll() |
||||
} |
||||
// @formatter:on |
||||
return http.build() |
||||
} |
||||
|
||||
@Bean |
||||
open fun testController(testService: TestService): TestController { |
||||
return TestController(testService()) |
||||
} |
||||
|
||||
@Bean |
||||
open fun testService(): TestService { |
||||
return TestServiceImpl() |
||||
} |
||||
} |
||||
|
||||
@RestController |
||||
internal open class TestController(private val testService: TestService) { |
||||
@GetMapping(value = ["/anonymous", "/rememberMe", "/user"]) |
||||
@ResponseStatus(HttpStatus.OK) |
||||
fun httpRequest() { |
||||
} |
||||
|
||||
@GetMapping("/preAuthorize") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
fun preAuthorize() { |
||||
testService.preAuthorize() |
||||
} |
||||
} |
||||
|
||||
internal interface TestService { |
||||
@PreAuthorize("hasRole('user')") |
||||
fun preAuthorize() |
||||
} |
||||
|
||||
internal open class TestServiceImpl : TestService { |
||||
override fun preAuthorize() { |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* |
||||
* 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.authorization.customizingauthorizationmanagers |
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory |
||||
import org.springframework.security.authorization.AuthorizationManagers |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory |
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext |
||||
import org.springframework.stereotype.Component |
||||
|
||||
/** |
||||
* Documentation for {@link AuthorizationManagerFactory}. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
// tag::class[] |
||||
@Component |
||||
class CustomHttpRequestsAuthorizationManagerFactory : AuthorizationManagerFactory<RequestAuthorizationContext> { |
||||
private val delegate = DefaultAuthorizationManagerFactory<RequestAuthorizationContext>() |
||||
|
||||
override fun authenticated(): AuthorizationManager<RequestAuthorizationContext> { |
||||
return AuthorizationManagers.allOf( |
||||
delegate.authenticated(), |
||||
delegate.hasRole("USER") |
||||
) |
||||
} |
||||
} |
||||
// end::class[] |
||||
|
||||
|
||||
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
/* |
||||
* 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.authorization.customizingauthorizationmanagers |
||||
|
||||
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.http.HttpStatus |
||||
import org.springframework.security.authentication.TestingAuthenticationToken |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication |
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers |
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status |
||||
import org.springframework.web.bind.annotation.GetMapping |
||||
import org.springframework.web.bind.annotation.ResponseStatus |
||||
import org.springframework.web.bind.annotation.RestController |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
/** |
||||
* Tests for [CustomHttpRequestsAuthorizationManagerFactory]. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class CustomHttpRequestsAuthorizationManagerFactoryTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getHelloWhenAnonymousThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire() |
||||
// @formatter:off |
||||
mockMvc.perform(get("/hello").with(anonymous())) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(SecurityMockMvcResultMatchers.unauthenticated()) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getHelloWhenAuthenticatedWithUserRoleThenOk() { |
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_USER") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getHelloWhenAuthenticatedWithOtherRoleThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getHelloWhenAuthenticatedWithNoRolesThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", listOf()) |
||||
// @formatter:off |
||||
mockMvc.perform(get("/hello").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@Configuration |
||||
internal open class SecurityConfiguration { |
||||
@Bean |
||||
@Throws(Exception::class) |
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeHttpRequests { authorize -> |
||||
authorize.anyRequest().authenticated() |
||||
} |
||||
// @formatter:on |
||||
return http.build() |
||||
} |
||||
|
||||
@Bean |
||||
open fun customHttpRequestsAuthorizationManagerFactory(): CustomHttpRequestsAuthorizationManagerFactory { |
||||
return CustomHttpRequestsAuthorizationManagerFactory() |
||||
} |
||||
} |
||||
|
||||
@RestController |
||||
internal class TestController { |
||||
@GetMapping("/**") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
fun ok() { |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* 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.authorization.customizingauthorizationmanagers |
||||
|
||||
import org.aopalliance.intercept.MethodInvocation |
||||
import org.springframework.security.authorization.AuthorizationManager |
||||
import org.springframework.security.authorization.AuthorizationManagerFactory |
||||
import org.springframework.security.authorization.AuthorizationManagers |
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory |
||||
import org.springframework.stereotype.Component |
||||
|
||||
/** |
||||
* Documentation for [AuthorizationManagerFactory]. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
// tag::class[] |
||||
@Component |
||||
class CustomMethodInvocationAuthorizationManagerFactory : AuthorizationManagerFactory<MethodInvocation> { |
||||
private val delegate = DefaultAuthorizationManagerFactory<MethodInvocation>() |
||||
|
||||
override fun hasRole(role: String): AuthorizationManager<MethodInvocation> { |
||||
return AuthorizationManagers.anyOf( |
||||
delegate.hasRole(role), |
||||
delegate.hasRole("ADMIN") |
||||
) |
||||
} |
||||
|
||||
override fun hasAnyRole(vararg roles: String): AuthorizationManager<MethodInvocation> { |
||||
return AuthorizationManagers.anyOf( |
||||
delegate.hasAnyRole(*roles), |
||||
delegate.hasRole("ADMIN") |
||||
) |
||||
} |
||||
} |
||||
// end::class[] |
||||
|
||||
@ -0,0 +1,215 @@
@@ -0,0 +1,215 @@
|
||||
/* |
||||
* 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.authorization.customizingauthorizationmanagers |
||||
|
||||
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.http.HttpStatus |
||||
import org.springframework.security.access.prepost.PreAuthorize |
||||
import org.springframework.security.authentication.TestingAuthenticationToken |
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.test.SpringTestContext |
||||
import org.springframework.security.config.test.SpringTestContextExtension |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous |
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication |
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated |
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated |
||||
import org.springframework.security.web.SecurityFilterChain |
||||
import org.springframework.test.web.servlet.MockMvc |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status |
||||
import org.springframework.web.bind.annotation.GetMapping |
||||
import org.springframework.web.bind.annotation.ResponseStatus |
||||
import org.springframework.web.bind.annotation.RestController |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc |
||||
|
||||
/** |
||||
* Tests for [CustomMethodInvocationAuthorizationManagerFactory]. |
||||
* |
||||
* @author Steve Riesenberg |
||||
*/ |
||||
@ExtendWith(SpringTestContextExtension::class) |
||||
class CustomMethodInvocationAuthorizationManagerFactoryTests { |
||||
@JvmField |
||||
val spring = SpringTestContext(this) |
||||
|
||||
@Autowired |
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenAnonymousThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(anonymous())) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(unauthenticated()) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenAuthenticatedWithNoRolesThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", listOf()) |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenAuthenticatedWithUserRoleThenOk() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_USER") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenAuthenticatedWithAdminRoleThenOk() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ADMIN") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getUserWhenAuthenticatedWithOtherRoleThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/user").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getRolesWhenAuthenticatedWithRole1RoleThenOk() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ROLE1") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getRolesWhenAuthenticatedWithAdminRoleThenOk() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ADMIN") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@Test |
||||
@Throws(Exception::class) |
||||
fun getRolesWhenAuthenticatedWithOtherRoleThenForbidden() { |
||||
spring.register(SecurityConfiguration::class.java).autowire() |
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER") |
||||
// @formatter:off |
||||
mockMvc.perform(get("/roles").with(authentication(authentication))) |
||||
.andExpect(status().isForbidden()) |
||||
.andExpect(authenticated().withAuthentication(authentication)) |
||||
// @formatter:on |
||||
} |
||||
|
||||
@EnableWebMvc |
||||
@EnableWebSecurity |
||||
@EnableMethodSecurity |
||||
@Configuration |
||||
internal open class SecurityConfiguration { |
||||
@Bean |
||||
@Throws(Exception::class) |
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { |
||||
// @formatter:off |
||||
http |
||||
.authorizeHttpRequests { authorize -> |
||||
authorize.anyRequest().authenticated() |
||||
} |
||||
// @formatter:on |
||||
return http.build() |
||||
} |
||||
|
||||
@Bean |
||||
open fun customMethodInvocationAuthorizationManagerFactory(): CustomMethodInvocationAuthorizationManagerFactory { |
||||
return CustomMethodInvocationAuthorizationManagerFactory() |
||||
} |
||||
|
||||
@Bean |
||||
open fun testController(testService: TestService): TestController { |
||||
return TestController(testService()) |
||||
} |
||||
|
||||
@Bean |
||||
open fun testService(): TestService { |
||||
return TestServiceImpl() |
||||
} |
||||
} |
||||
|
||||
@RestController |
||||
internal open class TestController(private val testService: TestService) { |
||||
@GetMapping("/user") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
fun user() { |
||||
testService.user() |
||||
} |
||||
|
||||
@GetMapping("/roles") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
fun roles() { |
||||
testService.roles() |
||||
} |
||||
} |
||||
|
||||
internal interface TestService { |
||||
@PreAuthorize("hasRole('USER')") |
||||
fun user() |
||||
|
||||
@PreAuthorize("hasAnyRole('ROLE1', 'ROLE2')") |
||||
fun roles() |
||||
} |
||||
|
||||
internal open class TestServiceImpl : TestService { |
||||
override fun user() { |
||||
} |
||||
|
||||
override fun roles() { |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ 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. |
||||
--> |
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation=" |
||||
http://www.springframework.org/schema/beans |
||||
https://www.springframework.org/schema/beans/spring-beans.xsd"> |
||||
|
||||
<!-- tag::config[] --> |
||||
<b:bean id="authorizationManagerFactory" class="org.springframework.security.authorization.DefaultAuthorizationManagerFactory"> |
||||
<b:property name="trustResolver" ref="authenticationTrustResolver"/> |
||||
<b:property name="roleHierarchy" ref="roleHierarchy"/> |
||||
<b:property name="rolePrefix" value="role_"/> |
||||
</b:bean> |
||||
<!-- end::config[] --> |
||||
|
||||
<b:bean id="authenticationTrustResolver" class="org.springframework.security.authentication.AuthenticationTrustResolverImpl"> |
||||
<b:property name="anonymousClass" value="org.springframework.security.authentication.TestingAuthenticationToken"/> |
||||
</b:bean> |
||||
|
||||
<b:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl" factory-method="fromHierarchy"> |
||||
<b:constructor-arg name="hierarchy" value="role_admin > role_user"/> |
||||
</b:bean> |
||||
|
||||
</b:beans> |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* 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.web.access.expression; |
||||
|
||||
import java.util.function.Supplier; |
||||
|
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.web.FilterInvocation; |
||||
import org.springframework.security.web.util.matcher.IpAddressMatcher; |
||||
|
||||
/** |
||||
* @author Steve Riesenberg |
||||
* @since 7.0 |
||||
*/ |
||||
final class FilterInvocationExpressionRoot extends SecurityExpressionRoot<FilterInvocation> { |
||||
|
||||
/** |
||||
* Allows direct access to the request object |
||||
*/ |
||||
public final HttpServletRequest request; |
||||
|
||||
/** |
||||
* Creates an instance for the given {@link Supplier} of the {@link Authentication} |
||||
* and {@link HttpServletRequest}. |
||||
* @param authentication the {@link Supplier} of the {@link Authentication} to use |
||||
* @param fi the {@link FilterInvocation} to use |
||||
*/ |
||||
FilterInvocationExpressionRoot(Supplier<Authentication> authentication, FilterInvocation fi) { |
||||
super(authentication, fi); |
||||
this.request = fi.getRequest(); |
||||
} |
||||
|
||||
/** |
||||
* Takes a specific IP address or a range using the IP/Netmask (e.g. 192.168.1.0/24 or |
||||
* 202.24.0.0/14). |
||||
* @param ipAddress the address or range of addresses from which the request must |
||||
* come. |
||||
* @return true if the IP address of the current request is in the required range. |
||||
*/ |
||||
public boolean hasIpAddress(String ipAddress) { |
||||
IpAddressMatcher matcher = new IpAddressMatcher(ipAddress); |
||||
return matcher.matches(this.request); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue