Add Not Support
Closes gh-14058
This commit is contained in:
+17
-1
@@ -30,6 +30,7 @@ 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.AuthorizationManagers;
|
||||
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
@@ -244,11 +245,14 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* {@link RequestMatcher}s.
|
||||
*
|
||||
* @author Evgeniy Cheban
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
public class AuthorizedUrl {
|
||||
|
||||
private final List<? extends RequestMatcher> matchers;
|
||||
|
||||
private boolean not;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
* @param matchers the {@link RequestMatcher} instances to map
|
||||
@@ -261,6 +265,16 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
return this.matchers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the following authorization rule.
|
||||
* @return the {@link AuthorizedUrl} for further customization
|
||||
* @since 6.3
|
||||
*/
|
||||
public AuthorizedUrl not() {
|
||||
this.not = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anyone.
|
||||
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
|
||||
@@ -382,7 +396,9 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
public AuthorizationManagerRequestMatcherRegistry access(
|
||||
AuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
Assert.notNull(manager, "manager cannot be null");
|
||||
return AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);
|
||||
return (this.not)
|
||||
? AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, AuthorizationManagers.not(manager))
|
||||
: AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
@@ -596,6 +596,20 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenNotConfigAndAuthenticatedThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(NotConfig.class, BasicController.class).autowire();
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/").with(user("user"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenNotConfigAndNotAuthenticatedThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(NotConfig.class, BasicController.class).autowire();
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/");
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class GrantedAuthorityDefaultHasRoleConfig {
|
||||
@@ -1136,6 +1150,24 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class NotConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain chain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeHttpRequests((requests) -> requests
|
||||
.anyRequest().not().authenticated()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AuthorizationEventPublisherConfig {
|
||||
|
||||
|
||||
+36
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
* A factory class to create an {@link AuthorizationManager} instances.
|
||||
*
|
||||
* @author Evgeniy Cheban
|
||||
* @author Josh Cummings
|
||||
* @since 5.8
|
||||
*/
|
||||
public final class AuthorizationManagers {
|
||||
@@ -119,6 +120,25 @@ public final class AuthorizationManagers {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link AuthorizationManager} that reverses whatever decision the given
|
||||
* {@link AuthorizationManager} granted. If the given {@link AuthorizationManager}
|
||||
* abstains, then the returned manager also abstains.
|
||||
* @param <T> the type of object that is being authorized
|
||||
* @param manager the {@link AuthorizationManager} to reverse
|
||||
* @return the reversing {@link AuthorizationManager}
|
||||
* @since 6.3
|
||||
*/
|
||||
public static <T> AuthorizationManager<T> not(AuthorizationManager<T> manager) {
|
||||
return (authentication, object) -> {
|
||||
AuthorizationDecision decision = manager.check(authentication, object);
|
||||
if (decision == null) {
|
||||
return null;
|
||||
}
|
||||
return new NotAuthorizationDecision(decision);
|
||||
};
|
||||
}
|
||||
|
||||
private AuthorizationManagers() {
|
||||
}
|
||||
|
||||
@@ -138,4 +158,20 @@ public final class AuthorizationManagers {
|
||||
|
||||
}
|
||||
|
||||
private static final class NotAuthorizationDecision extends AuthorizationDecision {
|
||||
|
||||
private final AuthorizationDecision decision;
|
||||
|
||||
private NotAuthorizationDecision(AuthorizationDecision decision) {
|
||||
super(!decision.isGranted());
|
||||
this.decision = decision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NotAuthorizationDecision [decision=" + this.decision + ']';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -224,4 +224,19 @@ class AuthorizationManagersTests {
|
||||
assertThat(decision).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkNotWhenEmptyThenAbstainedDecision() {
|
||||
AuthorizationManager<?> negated = AuthorizationManagers.not((a, o) -> null);
|
||||
AuthorizationDecision decision = negated.check(null, null);
|
||||
assertThat(decision).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkNotWhenGrantedThenDeniedDecision() {
|
||||
AuthorizationManager<?> negated = AuthorizationManagers.not((a, o) -> new AuthorizationDecision(true));
|
||||
AuthorizationDecision decision = negated.check(null, null);
|
||||
assertThat(decision).isNotNull();
|
||||
assertThat(decision.isGranted()).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user