mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-30 15:52:15 +00:00
Test Reactive Method Security Exactly-One Invocation Semantics
Issue gh-15651
This commit is contained in:
parent
1aec571a81
commit
75fd84ce16
@ -19,6 +19,7 @@ package org.springframework.security.config.annotation.method.configuration;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -58,6 +59,7 @@ import org.springframework.security.authorization.method.PrePostTemplateDefaults
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
@ -71,6 +73,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ -449,6 +452,20 @@ public class PrePostReactiveMethodSecurityConfigurationTests {
|
||||
"postFilterAuthorizationMethodInterceptor", "authorizeReturnObjectMethodInterceptor");
|
||||
}
|
||||
|
||||
// gh-15651
|
||||
@Test
|
||||
@WithMockUser(roles = "ADMIN")
|
||||
public void adviseWhenPrePostEnabledThenEachInterceptorRunsExactlyOnce() {
|
||||
this.spring
|
||||
.register(MethodSecurityServiceEnabledConfig.class, CustomMethodSecurityExpressionHandlerConfig.class)
|
||||
.autowire();
|
||||
MethodSecurityExpressionHandler expressionHandler = this.spring.getContext()
|
||||
.getBean(MethodSecurityExpressionHandler.class);
|
||||
ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
|
||||
service.manyAnnotations(Mono.just(new ArrayList<>(Arrays.asList("harold", "jonathan", "tim", "bo")))).block();
|
||||
verify(expressionHandler, times(4)).createEvaluationContext(any(Authentication.class), any());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableReactiveMethodSecurity
|
||||
static class MethodSecurityServiceEnabledConfig {
|
||||
@ -460,6 +477,20 @@ public class PrePostReactiveMethodSecurityConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableReactiveMethodSecurity
|
||||
static class CustomMethodSecurityExpressionHandlerConfig {
|
||||
|
||||
private final MethodSecurityExpressionHandler expressionHandler = spy(
|
||||
new DefaultMethodSecurityExpressionHandler());
|
||||
|
||||
@Bean
|
||||
MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class PermissionEvaluatorConfig {
|
||||
|
||||
|
@ -21,6 +21,7 @@ import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import reactor.core.publisher.Mono;
|
||||
@ -31,7 +32,9 @@ import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.security.authorization.AuthorizationResult;
|
||||
import org.springframework.security.authorization.method.HandleAuthorizationDenied;
|
||||
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
|
||||
@ -104,6 +107,12 @@ public interface ReactiveMethodSecurityService {
|
||||
@PreAuthorize("hasPermission(#kgName, 'read')")
|
||||
Mono<String> preAuthorizeHasPermission(String kgName);
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostAuthorize("hasRole('ADMIN')")
|
||||
@PreFilter("true")
|
||||
@PostFilter("true")
|
||||
Mono<List<String>> manyAnnotations(Mono<List<String>> array);
|
||||
|
||||
class StarMaskingHandler implements MethodAuthorizationDeniedHandler {
|
||||
|
||||
@Override
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
@ -93,4 +95,9 @@ public class ReactiveMethodSecurityServiceImpl implements ReactiveMethodSecurity
|
||||
return Mono.just("ok");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<String>> manyAnnotations(Mono<List<String>> array) {
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user