EnableReactiveMethodSecurity
Spring Security supports method security by using Reactor’s Context, which is set up by ReactiveSecurityContextHolder.
The following example shows how to retrieve the currently logged in user’s message:
|
For this example to work, the return type of the method must be a |
EnableReactiveMethodSecurity with AuthorizationManager
In Spring Security 5.8, we can enable annotation-based security using the @EnableReactiveMethodSecurity(useAuthorizationManager=true) annotation on any @Configuration instance.
This improves upon @EnableReactiveMethodSecurity in a number of ways. @EnableReactiveMethodSecurity(useAuthorizationManager=true):
-
Uses the simplified
AuthorizationManagerAPI instead of metadata sources, config attributes, decision managers, and voters. This simplifies reuse and customization. -
Supports reactive return types including Kotlin coroutines.
-
Is built using native Spring AOP, removing abstractions and allowing you to use Spring AOP building blocks to customize
-
Checks for conflicting annotations to ensure an unambiguous security configuration
-
Complies with JSR-250
|
For earlier versions, please read about similar support with @EnableReactiveMethodSecurity. |
For example, the following would enable Spring Security’s @PreAuthorize annotation:
-
Java
@EnableReactiveMethodSecurity(useAuthorizationManager=true)
public class MethodSecurityConfig {
// ...
}
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
Spring Security’s native annotation support defines a set of attributes for the method.
These will be passed to the various method interceptors, like AuthorizationManagerBeforeReactiveMethodInterceptor, for it to make the actual decision:
-
Java
public interface BankService {
@PreAuthorize("hasRole('USER')")
Mono<Account> readAccount(Long id);
@PreAuthorize("hasRole('USER')")
Flux<Account> findAccounts();
@PreAuthorize("@func.apply(#account)")
Mono<Account> post(Account account, Double amount);
}
In this case hasRole refers to the method found in SecurityExpressionRoot that gets invoked by the SpEL evaluation engine.
@bean refers to a custom component you have defined, where apply can return Boolean or Mono<Boolean> to indicate the authorization decision.
A bean like that might look something like this:
-
Java
@Bean
public Function<Account, Mono<Boolean>> func() {
return (account) -> Mono.defer(() -> Mono.just(account.getId().equals(12)));
}
Method authorization is a combination of before- and after-method authorization.
|
Before-method authorization is performed before the method is invoked.
If that authorization denies access, the method is not invoked, and an |
To recreate what adding @EnableReactiveMethodSecurity(useAuthorizationManager=true) does by default, you would publish the following configuration:
-
Java
@Configuration
class MethodSecurityConfig {
@Bean
BeanDefinitionRegistryPostProcessor aopConfig() {
return AopConfigUtils::registerAutoProxyCreatorIfNecessary;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor() {
return new PreFilterAuthorizationReactiveMethodInterceptor();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor() {
return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor() {
return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor() {
return new PostFilterAuthorizationReactiveMethodInterceptor();
}
}
Notice that Spring Security’s method security is built using Spring AOP.