Add AuthorizationManagerFactory
Signed-off-by: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com>
This commit is contained in:
committed by
Rob Winch
parent
a4f813ab29
commit
eeb4574bb3
+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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+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[]
|
||||
+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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+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[]
|
||||
+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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+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")
|
||||
}
|
||||
+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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+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[]
|
||||
|
||||
|
||||
+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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+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[]
|
||||
|
||||
+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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+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>
|
||||
Reference in New Issue
Block a user