1
0
mirror of synced 2026-08-05 09:47:05 +00:00

Add AuthorizationManagerFactory

Signed-off-by: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com>
This commit is contained in:
Steve Riesenberg
2025-09-02 12:47:53 -05:00
committed by Rob Winch
parent a4f813ab29
commit eeb4574bb3
37 changed files with 2719 additions and 178 deletions
@@ -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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
/*
* 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 @@
<?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>