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
+6
@@ -39,6 +39,7 @@ import org.springframework.security.aot.hint.PrePostAuthorizeHintsRegistrar;
|
||||
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
|
||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
@@ -121,6 +122,11 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, Applicati
|
||||
this.expressionHandler.setRoleHierarchy(roleHierarchy);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setAuthorizationManagerFactory(AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory) {
|
||||
this.expressionHandler.setAuthorizationManagerFactory(authorizationManagerFactory);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
|
||||
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||
|
||||
+57
-35
@@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -27,13 +26,12 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.AuthorizationManagers;
|
||||
import org.springframework.security.authorization.SingleResultAuthorizationManager;
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
|
||||
import org.springframework.security.config.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
@@ -46,13 +44,13 @@ import org.springframework.security.web.access.intercept.RequestMatcherDelegatin
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
/**
|
||||
* Adds a URL based authorization using {@link AuthorizationManager}.
|
||||
*
|
||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured.
|
||||
* @author Evgeniy Cheban
|
||||
* @author Steve Riesenberg
|
||||
* @since 5.5
|
||||
*/
|
||||
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
@@ -62,9 +60,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
|
||||
private final AuthorizationEventPublisher publisher;
|
||||
|
||||
private final Supplier<RoleHierarchy> roleHierarchy;
|
||||
|
||||
private String rolePrefix = "ROLE_";
|
||||
private final AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;
|
||||
|
||||
private ObjectPostProcessor<AuthorizationManager<HttpServletRequest>> postProcessor = ObjectPostProcessor
|
||||
.identity();
|
||||
@@ -81,13 +77,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
else {
|
||||
this.publisher = new SpringAuthorizationEventPublisher(context);
|
||||
}
|
||||
this.roleHierarchy = SingletonSupplier.of(() -> (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
|
||||
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy());
|
||||
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
|
||||
if (grantedAuthorityDefaultsBeanNames.length > 0) {
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(GrantedAuthorityDefaults.class);
|
||||
this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
|
||||
}
|
||||
this.authorizationManagerFactory = getAuthorizationManagerFactory(context);
|
||||
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class,
|
||||
ResolvableType.forClassWithGenerics(AuthorizationManager.class, HttpServletRequest.class));
|
||||
ObjectProvider<ObjectPostProcessor<AuthorizationManager<HttpServletRequest>>> provider = context
|
||||
@@ -95,6 +85,35 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
provider.ifUnique((postProcessor) -> this.postProcessor = postProcessor);
|
||||
}
|
||||
|
||||
private AuthorizationManagerFactory<RequestAuthorizationContext> getAuthorizationManagerFactory(
|
||||
ApplicationContext context) {
|
||||
ResolvableType authorizationManagerFactoryType = ResolvableType
|
||||
.forClassWithGenerics(AuthorizationManagerFactory.class, RequestAuthorizationContext.class);
|
||||
|
||||
// Handle fallback to generic type
|
||||
if (context.getBeanNamesForType(authorizationManagerFactoryType).length == 0) {
|
||||
authorizationManagerFactoryType = ResolvableType.forClassWithGenerics(AuthorizationManagerFactory.class,
|
||||
Object.class);
|
||||
}
|
||||
|
||||
ObjectProvider<AuthorizationManagerFactory<RequestAuthorizationContext>> authorizationManagerFactoryProvider = context
|
||||
.getBeanProvider(authorizationManagerFactoryType);
|
||||
|
||||
return authorizationManagerFactoryProvider.getIfAvailable(() -> {
|
||||
RoleHierarchy roleHierarchy = context.getBeanProvider(RoleHierarchy.class)
|
||||
.getIfAvailable(NullRoleHierarchy::new);
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBeanProvider(GrantedAuthorityDefaults.class)
|
||||
.getIfAvailable();
|
||||
String rolePrefix = (grantedAuthorityDefaults != null) ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
|
||||
|
||||
DefaultAuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = new DefaultAuthorizationManagerFactory<>();
|
||||
authorizationManagerFactory.setRoleHierarchy(roleHierarchy);
|
||||
authorizationManagerFactory.setRolePrefix(rolePrefix);
|
||||
|
||||
return authorizationManagerFactory;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link AuthorizationManagerRequestMatcherRegistry} is what users will interact
|
||||
* with after applying the {@link AuthorizeHttpRequestsConfigurer}.
|
||||
@@ -173,7 +192,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
@Override
|
||||
protected AuthorizedUrl chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
||||
this.unmappedMatchers = requestMatchers;
|
||||
return new AuthorizedUrl(requestMatchers);
|
||||
return new AuthorizedUrl(requestMatchers, AuthorizeHttpRequestsConfigurer.this.authorizationManagerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,20 +220,31 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
|
||||
private final List<? extends RequestMatcher> matchers;
|
||||
|
||||
private AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;
|
||||
|
||||
private boolean not;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
* @param matchers the {@link RequestMatcher} instances to map
|
||||
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} for
|
||||
* creating instances of {@link AuthorizationManager}
|
||||
*/
|
||||
AuthorizedUrl(List<? extends RequestMatcher> matchers) {
|
||||
AuthorizedUrl(List<? extends RequestMatcher> matchers,
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
|
||||
this.matchers = matchers;
|
||||
this.authorizationManagerFactory = authorizationManagerFactory;
|
||||
}
|
||||
|
||||
protected List<? extends RequestMatcher> getMatchers() {
|
||||
return this.matchers;
|
||||
}
|
||||
|
||||
void setAuthorizationManagerFactory(
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
|
||||
this.authorizationManagerFactory = authorizationManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the following authorization rule.
|
||||
* @return the {@link AuthorizedUrl} for further customization
|
||||
@@ -231,7 +261,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry permitAll() {
|
||||
return access(SingleResultAuthorizationManager.permitAll());
|
||||
return access(this.authorizationManagerFactory.permitAll());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +270,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry denyAll() {
|
||||
return access(SingleResultAuthorizationManager.denyAll());
|
||||
return access(this.authorizationManagerFactory.denyAll());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,8 +281,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
|
||||
return access(withRoleHierarchy(AuthorityAuthorizationManager
|
||||
.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, new String[] { role })));
|
||||
return access(this.authorizationManagerFactory.hasRole(role));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,8 +293,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
|
||||
return access(withRoleHierarchy(
|
||||
AuthorityAuthorizationManager.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, roles)));
|
||||
return access(this.authorizationManagerFactory.hasAnyRole(roles));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +303,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority) {
|
||||
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)));
|
||||
return access(this.authorizationManagerFactory.hasAuthority(authority));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,13 +314,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
|
||||
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
|
||||
}
|
||||
|
||||
private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHierarchy(
|
||||
AuthorityAuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
manager.setRoleHierarchy(AuthorizeHttpRequestsConfigurer.this.roleHierarchy.get());
|
||||
return manager;
|
||||
return access(this.authorizationManagerFactory.hasAnyAuthority(authorities));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,7 +323,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry authenticated() {
|
||||
return access(AuthenticatedAuthorizationManager.authenticated());
|
||||
return access(this.authorizationManagerFactory.authenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +335,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* @see RememberMeConfigurer
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
|
||||
return access(AuthenticatedAuthorizationManager.fullyAuthenticated());
|
||||
return access(this.authorizationManagerFactory.fullyAuthenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,7 +346,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* @see RememberMeConfigurer
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry rememberMe() {
|
||||
return access(AuthenticatedAuthorizationManager.rememberMe());
|
||||
return access(this.authorizationManagerFactory.rememberMe());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +356,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* @since 5.8
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry anonymous() {
|
||||
return access(AuthenticatedAuthorizationManager.anonymous());
|
||||
return access(this.authorizationManagerFactory.anonymous());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+322
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
@@ -36,14 +37,19 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.AuthorizationObservationContext;
|
||||
import org.springframework.security.authorization.SingleResultAuthorizationManager;
|
||||
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
|
||||
import org.springframework.security.config.ObjectPostProcessor;
|
||||
@@ -82,13 +88,17 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
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.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
@@ -170,6 +180,26 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
.withMessageContaining("manager cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenCustomAuthorizationManagerFactoryRegisteredThenUsed() {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class).autowire();
|
||||
verify(authorizationManagerFactory).permitAll();
|
||||
verify(authorizationManagerFactory).denyAll();
|
||||
verify(authorizationManagerFactory).hasRole("ADMIN");
|
||||
verify(authorizationManagerFactory).hasAnyRole("USER", "ADMIN");
|
||||
verify(authorizationManagerFactory).hasAuthority("write");
|
||||
verify(authorizationManagerFactory).hasAnyAuthority("resource.read", "read");
|
||||
verify(authorizationManagerFactory).authenticated();
|
||||
verify(authorizationManagerFactory).fullyAuthenticated();
|
||||
verify(authorizationManagerFactory).rememberMe();
|
||||
verify(authorizationManagerFactory).anonymous();
|
||||
verifyNoMoreInteractions(authorizationManagerFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenObjectPostProcessorRegisteredThenInvokedOnAuthorizationManagerAndAuthorizationFilter() {
|
||||
this.spring.register(ObjectPostProcessorConfig.class).autowire();
|
||||
@@ -538,6 +568,205 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndPermitAllThenRespondsWithOk() throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> permitAll = spy(SingleResultAuthorizationManager.permitAll());
|
||||
given(authorizationManagerFactory.permitAll()).willReturn(permitAll);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/public").with(anonymous());
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(permitAll).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(permitAll);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndDenyAllThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> denyAll = spy(SingleResultAuthorizationManager.denyAll());
|
||||
given(authorizationManagerFactory.denyAll()).willReturn(denyAll);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/private").with(user("user"));
|
||||
this.mvc.perform(request).andExpect(status().isForbidden());
|
||||
verify(denyAll).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(denyAll);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndHasRoleThenRespondsWithOk() throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> hasRole = spy(AuthorityAuthorizationManager.hasRole("ADMIN"));
|
||||
given(authorizationManagerFactory.hasRole(anyString())).willReturn(hasRole);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/admin").with(user("admin").roles("ADMIN"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(hasRole).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(hasRole);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndHasAnyRoleThenRespondsWithOk() throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> hasAnyRole = spy(
|
||||
AuthorityAuthorizationManager.hasAnyRole("USER", "ADMIN"));
|
||||
given(authorizationManagerFactory.hasAnyRole(any(String[].class))).willReturn(hasAnyRole);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/user").with(user("user").roles("USER"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(hasAnyRole).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(hasAnyRole);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenCustomAuthorizationManagerFactoryRegisteredAndHasAuthorityThenRespondsWithOk()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> hasAuthority = spy(
|
||||
AuthorityAuthorizationManager.hasAuthority("write"));
|
||||
given(authorizationManagerFactory.hasAuthority(anyString())).willReturn(hasAuthority);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = post("/resource")
|
||||
.with(user("user").authorities(new SimpleGrantedAuthority("write")))
|
||||
.with(csrf());
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(hasAuthority).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(hasAuthority);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndHasAnyAuthorityThenRespondsWithOk()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> hasAnyAuthority = spy(
|
||||
AuthorityAuthorizationManager.hasAnyAuthority("resource.read", "read"));
|
||||
given(authorizationManagerFactory.hasAnyAuthority(any(String[].class))).willReturn(hasAnyAuthority);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/resource")
|
||||
.with(user("user").authorities(new SimpleGrantedAuthority("read")));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(hasAnyAuthority).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(hasAnyAuthority);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndAuthenticatedThenRespondsWithOk()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> authenticated = spy(
|
||||
AuthenticatedAuthorizationManager.authenticated());
|
||||
given(authorizationManagerFactory.authenticated()).willReturn(authenticated);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/authenticated").with(user("user"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(authenticated).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(authenticated);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndFullyAuthenticatedThenRespondsWithOk()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> fullyAuthenticated = spy(
|
||||
AuthenticatedAuthorizationManager.fullyAuthenticated());
|
||||
given(authorizationManagerFactory.fullyAuthenticated()).willReturn(fullyAuthenticated);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/fully-authenticated").with(user("user"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(fullyAuthenticated).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(fullyAuthenticated);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndRememberMeThenRespondsWithOk() throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> rememberMe = spy(
|
||||
AuthenticatedAuthorizationManager.rememberMe());
|
||||
given(authorizationManagerFactory.rememberMe()).willReturn(rememberMe);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/remember-me")
|
||||
.with(authentication(new RememberMeAuthenticationToken("test", "user", Set.of())));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(rememberMe).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(rememberMe);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndAnonymousThenRespondsWithOk() throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
AuthorizationManager<RequestAuthorizationContext> anonymous = spy(
|
||||
AuthenticatedAuthorizationManager.anonymous());
|
||||
given(authorizationManagerFactory.anonymous()).willReturn(anonymous);
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = authorizationManagerFactory;
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class, AccessTestController.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/anonymous").with(anonymous());
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(anonymous).authorize(any(), any(RequestAuthorizationContext.class));
|
||||
verifyNoMoreInteractions(anonymous);
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomAuthorizationManagerFactoryRegisteredAndAccessThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager = mock();
|
||||
AuthorizationManagerFactoryConfig.authorizationManagerFactory = mockAuthorizationManagerFactory(
|
||||
authorizationManager);
|
||||
|
||||
this.spring.register(AuthorizationManagerFactoryConfig.class).autowire();
|
||||
MockHttpServletRequestBuilder request = get("/").with(user("user"));
|
||||
this.mvc.perform(request).andExpect(status().isForbidden());
|
||||
verifyNoInteractions(authorizationManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenExpressionHasIpAddressLocalhostConfiguredIpAddressIsLocalhostThenRespondsWithOk()
|
||||
throws Exception {
|
||||
@@ -587,6 +816,23 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
};
|
||||
}
|
||||
|
||||
private AuthorizationManagerFactory<RequestAuthorizationContext> mockAuthorizationManagerFactory(
|
||||
AuthorizationManager<RequestAuthorizationContext> authorizationManager) {
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = mock();
|
||||
given(authorizationManagerFactory.permitAll()).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.denyAll()).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.hasRole(anyString())).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.hasAnyRole(any(String[].class))).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.hasAuthority(anyString())).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.hasAnyAuthority(any(String[].class))).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.authenticated()).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.fullyAuthenticated()).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.rememberMe()).willReturn(authorizationManager);
|
||||
given(authorizationManagerFactory.anonymous()).willReturn(authorizationManager);
|
||||
|
||||
return authorizationManagerFactory;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenFullyAuthenticatedConfiguredAndRememberMeTokenThenRespondsWithUnauthorized() throws Exception {
|
||||
this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
|
||||
@@ -850,6 +1096,41 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class AuthorizationManagerFactoryConfig {
|
||||
|
||||
static AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;
|
||||
|
||||
@Bean
|
||||
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory() {
|
||||
return authorizationManagerFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers("/public").permitAll()
|
||||
.requestMatchers("/private").denyAll()
|
||||
.requestMatchers("/admin").hasRole("ADMIN")
|
||||
.requestMatchers("/user").hasAnyRole("USER", "ADMIN")
|
||||
.requestMatchers(HttpMethod.POST, "/resource").hasAuthority("write")
|
||||
.requestMatchers("/resource").hasAnyAuthority("resource.read", "read")
|
||||
.requestMatchers("/authenticated").authenticated()
|
||||
.requestMatchers("/fully-authenticated").fullyAuthenticated()
|
||||
.requestMatchers("/remember-me").rememberMe()
|
||||
.requestMatchers("/anonymous").anonymous()
|
||||
.anyRequest().access((authentication, context) -> new AuthorizationDecision(false))
|
||||
);
|
||||
// @formatter:on
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class ObjectPostProcessorConfig {
|
||||
@@ -1295,6 +1576,47 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class AccessTestController {
|
||||
|
||||
@RequestMapping("/public")
|
||||
void publicEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/private")
|
||||
void privateEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/admin")
|
||||
void adminEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/user")
|
||||
void userEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/resource")
|
||||
void resourceEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/authenticated")
|
||||
void authenticatedEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/fully-authenticated")
|
||||
void fullyAuthenticatedEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/remember-me")
|
||||
void rememberMeEndpoint() {
|
||||
}
|
||||
|
||||
@RequestMapping("/anonymous")
|
||||
void anonymousEndpoint() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ObservationRegistryConfig {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user