mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-25 05:22:16 +00:00
Merge branch '6.3.x'
This commit is contained in:
commit
6352877bc4
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2024 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.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.aopalliance.aop.Advice;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.aop.Pointcut;
|
||||||
|
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
||||||
|
import org.springframework.util.function.SingletonSupplier;
|
||||||
|
|
||||||
|
final class DeferringMethodInterceptor<M extends AuthorizationAdvisor> implements AuthorizationAdvisor {
|
||||||
|
|
||||||
|
private final Pointcut pointcut;
|
||||||
|
|
||||||
|
private final Supplier<M> delegate;
|
||||||
|
|
||||||
|
DeferringMethodInterceptor(Pointcut pointcut, Supplier<M> delegate) {
|
||||||
|
this.pointcut = pointcut;
|
||||||
|
this.delegate = SingletonSupplier.of(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
||||||
|
return this.delegate.get().invoke(invocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pointcut getPointcut() {
|
||||||
|
return this.pointcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Advice getAdvice() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return this.delegate.get().getOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPerInstance() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,27 +16,30 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
|
||||||
|
import org.springframework.aop.Pointcut;
|
||||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportAware;
|
import org.springframework.context.annotation.ImportAware;
|
||||||
import org.springframework.context.annotation.Role;
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
|
||||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||||
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
|
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
|
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
|
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
|
||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,42 +50,64 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|||||||
* @since 5.6
|
* @since 5.6
|
||||||
* @see EnableMethodSecurity
|
* @see EnableMethodSecurity
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(value = "_jsr250MethodSecurityConfiguration", proxyBeanMethods = false)
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
|
final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
|
||||||
|
|
||||||
private int interceptorOrderOffset;
|
private static final Pointcut pointcut = AuthorizationManagerBeforeMethodInterceptor.jsr250().getPointcut();
|
||||||
|
|
||||||
|
private final Jsr250AuthorizationManager authorizationManager = new Jsr250AuthorizationManager();
|
||||||
|
|
||||||
|
private AuthorizationManagerBeforeMethodInterceptor methodInterceptor = AuthorizationManagerBeforeMethodInterceptor
|
||||||
|
.jsr250(this.authorizationManager);
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor jsr250AuthorizationMethodInterceptor(
|
static MethodInterceptor jsr250AuthorizationMethodInterceptor(
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
ObjectProvider<Jsr250MethodSecurityConfiguration> _jsr250MethodSecurityConfiguration) {
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
Supplier<AuthorizationManagerBeforeMethodInterceptor> supplier = () -> {
|
||||||
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
|
Jsr250MethodSecurityConfiguration configuration = _jsr250MethodSecurityConfiguration.getObject();
|
||||||
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
|
return configuration.methodInterceptor;
|
||||||
Jsr250MethodSecurityConfiguration configuration) {
|
};
|
||||||
Jsr250AuthorizationManager jsr250 = new Jsr250AuthorizationManager();
|
return new DeferringMethodInterceptor<>(pointcut, supplier);
|
||||||
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
|
|
||||||
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
|
|
||||||
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
|
|
||||||
jsr250.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
|
|
||||||
defaultsProvider.ifAvailable((d) -> jsr250.setRolePrefix(d.getRolePrefix()));
|
|
||||||
SecurityContextHolderStrategy strategy = strategyProvider
|
|
||||||
.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
|
|
||||||
AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(
|
|
||||||
registryProvider, jsr250);
|
|
||||||
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
|
|
||||||
.jsr250(manager);
|
|
||||||
interceptor.setOrder(interceptor.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
interceptor.setSecurityContextHolderStrategy(strategy);
|
|
||||||
eventPublisherProvider.ifAvailable(interceptor::setAuthorizationEventPublisher);
|
|
||||||
return interceptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||||
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
||||||
this.interceptorOrderOffset = annotation.offset();
|
this.methodInterceptor.setOrder(this.methodInterceptor.getOrder() + annotation.offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setGrantedAuthorityDefaults(GrantedAuthorityDefaults defaults) {
|
||||||
|
this.authorizationManager.setRolePrefix(defaults.getRolePrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||||
|
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
|
||||||
|
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
|
||||||
|
this.authorizationManager.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
this.methodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setObservationRegistry(ObservationRegistry registry) {
|
||||||
|
if (registry.isNoop()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AuthorizationManager<MethodInvocation> observed = new ObservationAuthorizationManager<>(registry,
|
||||||
|
this.authorizationManager);
|
||||||
|
this.methodInterceptor = AuthorizationManagerBeforeMethodInterceptor.secured(observed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
||||||
|
this.methodInterceptor.setAuthorizationEventPublisher(eventPublisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,24 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import org.aopalliance.aop.Advice;
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.aop.Advisor;
|
||||||
|
import org.springframework.aop.Pointcut;
|
||||||
|
import org.springframework.aop.PointcutAdvisor;
|
||||||
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
||||||
|
|
||||||
class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
||||||
|
|
||||||
@ -49,9 +61,49 @@ class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
|||||||
if (!(definition instanceof RootBeanDefinition)) {
|
if (!(definition instanceof RootBeanDefinition)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RootBeanDefinition advisor = new RootBeanDefinition((RootBeanDefinition) definition);
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AdvisorWrapper.class);
|
||||||
|
builder.setFactoryMethod("of");
|
||||||
|
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
|
builder.addConstructorArgReference(interceptorName);
|
||||||
|
RootBeanDefinition advisor = (RootBeanDefinition) builder.getBeanDefinition();
|
||||||
advisor.setTargetType(Advisor.class);
|
advisor.setTargetType(Advisor.class);
|
||||||
registry.registerBeanDefinition(prefix + "Advisor", advisor);
|
registry.registerBeanDefinition(advisorName, advisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class AdvisorWrapper
|
||||||
|
implements PointcutAdvisor, MethodInterceptor, Ordered, AopInfrastructureBean {
|
||||||
|
|
||||||
|
private final AuthorizationAdvisor advisor;
|
||||||
|
|
||||||
|
private AdvisorWrapper(AuthorizationAdvisor advisor) {
|
||||||
|
this.advisor = advisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AdvisorWrapper of(AuthorizationAdvisor advisor) {
|
||||||
|
return new AdvisorWrapper(advisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Advice getAdvice() {
|
||||||
|
return this.advisor.getAdvice();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pointcut getPointcut() {
|
||||||
|
return this.advisor.getPointcut();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return this.advisor.getOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
||||||
|
return this.advisor.invoke(invocation);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,17 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import org.aopalliance.aop.Advice;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.aop.Pointcut;
|
import org.springframework.aop.Pointcut;
|
||||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportAware;
|
import org.springframework.context.annotation.ImportAware;
|
||||||
@ -38,11 +34,9 @@ import org.springframework.context.annotation.Role;
|
|||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
|
||||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
|
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
|
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
|
||||||
@ -53,7 +47,6 @@ import org.springframework.security.authorization.method.PrePostTemplateDefaults
|
|||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.util.function.SingletonSupplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base {@link Configuration} for enabling Spring Security Method Security.
|
* Base {@link Configuration} for enabling Spring Security Method Security.
|
||||||
@ -63,172 +56,150 @@ import org.springframework.util.function.SingletonSupplier;
|
|||||||
* @since 5.6
|
* @since 5.6
|
||||||
* @see EnableMethodSecurity
|
* @see EnableMethodSecurity
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(value = "_prePostMethodSecurityConfiguration", proxyBeanMethods = false)
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
|
final class PrePostMethodSecurityConfiguration implements ImportAware, ApplicationContextAware, AopInfrastructureBean {
|
||||||
|
|
||||||
private int interceptorOrderOffset;
|
private static final Pointcut preFilterPointcut = new PreFilterAuthorizationMethodInterceptor().getPointcut();
|
||||||
|
|
||||||
|
private static final Pointcut preAuthorizePointcut = AuthorizationManagerBeforeMethodInterceptor.preAuthorize()
|
||||||
|
.getPointcut();
|
||||||
|
|
||||||
|
private static final Pointcut postAuthorizePointcut = AuthorizationManagerAfterMethodInterceptor.postAuthorize()
|
||||||
|
.getPointcut();
|
||||||
|
|
||||||
|
private static final Pointcut postFilterPointcut = new PostFilterAuthorizationMethodInterceptor().getPointcut();
|
||||||
|
|
||||||
|
private final PreAuthorizeAuthorizationManager preAuthorizeAuthorizationManager = new PreAuthorizeAuthorizationManager();
|
||||||
|
|
||||||
|
private final PostAuthorizeAuthorizationManager postAuthorizeAuthorizationManager = new PostAuthorizeAuthorizationManager();
|
||||||
|
|
||||||
|
private final PreFilterAuthorizationMethodInterceptor preFilterMethodInterceptor = new PreFilterAuthorizationMethodInterceptor();
|
||||||
|
|
||||||
|
private AuthorizationManagerBeforeMethodInterceptor preAuthorizeMethodInterceptor = AuthorizationManagerBeforeMethodInterceptor
|
||||||
|
.preAuthorize(this.preAuthorizeAuthorizationManager);
|
||||||
|
|
||||||
|
private AuthorizationManagerAfterMethodInterceptor postAuthorizeMethodInterceptor = AuthorizationManagerAfterMethodInterceptor
|
||||||
|
.postAuthorize(this.postAuthorizeAuthorizationManager);
|
||||||
|
|
||||||
|
private final PostFilterAuthorizationMethodInterceptor postFilterMethodInterceptor = new PostFilterAuthorizationMethodInterceptor();
|
||||||
|
|
||||||
|
private final DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||||
|
|
||||||
|
{
|
||||||
|
this.preFilterMethodInterceptor.setExpressionHandler(this.expressionHandler);
|
||||||
|
this.preAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||||
|
this.postAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||||
|
this.postFilterMethodInterceptor.setExpressionHandler(this.expressionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
|
this.expressionHandler.setApplicationContext(context);
|
||||||
|
this.preAuthorizeAuthorizationManager.setApplicationContext(context);
|
||||||
|
this.postAuthorizeAuthorizationManager.setApplicationContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setGrantedAuthorityDefaults(GrantedAuthorityDefaults grantedAuthorityDefaults) {
|
||||||
|
this.expressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||||
|
this.expressionHandler.setRoleHierarchy(roleHierarchy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
|
||||||
|
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
|
this.preAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
||||||
|
this.postAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
||||||
|
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setTemplateDefaults(PrePostTemplateDefaults templateDefaults) {
|
||||||
|
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
|
this.preAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
||||||
|
this.postAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
||||||
|
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||||
|
this.preFilterMethodInterceptor.setExpressionHandler(expressionHandler);
|
||||||
|
this.preAuthorizeAuthorizationManager.setExpressionHandler(expressionHandler);
|
||||||
|
this.postAuthorizeAuthorizationManager.setExpressionHandler(expressionHandler);
|
||||||
|
this.postFilterMethodInterceptor.setExpressionHandler(expressionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
this.preFilterMethodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
this.preAuthorizeMethodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
this.postAuthorizeMethodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
this.postFilterMethodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setObservationRegistry(ObservationRegistry registry) {
|
||||||
|
if (registry.isNoop()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.preAuthorizeMethodInterceptor = AuthorizationManagerBeforeMethodInterceptor
|
||||||
|
.preAuthorize(new ObservationAuthorizationManager<>(registry, this.preAuthorizeAuthorizationManager));
|
||||||
|
this.postAuthorizeMethodInterceptor = AuthorizationManagerAfterMethodInterceptor
|
||||||
|
.postAuthorize(new ObservationAuthorizationManager<>(registry, this.postAuthorizeAuthorizationManager));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setAuthorizationEventPublisher(AuthorizationEventPublisher publisher) {
|
||||||
|
this.preAuthorizeMethodInterceptor.setAuthorizationEventPublisher(publisher);
|
||||||
|
this.postAuthorizeMethodInterceptor.setAuthorizationEventPublisher(publisher);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor preFilterAuthorizationMethodInterceptor(
|
static MethodInterceptor preFilterAuthorizationMethodInterceptor(
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
ObjectProvider<PrePostMethodSecurityConfiguration> _prePostMethodSecurityConfiguration) {
|
||||||
ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
|
return new DeferringMethodInterceptor<>(preFilterPointcut,
|
||||||
ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
|
() -> _prePostMethodSecurityConfiguration.getObject().preFilterMethodInterceptor);
|
||||||
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
|
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
|
||||||
ObjectProvider<RoleHierarchy> roleHierarchyProvider, PrePostMethodSecurityConfiguration configuration,
|
|
||||||
ApplicationContext context) {
|
|
||||||
PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
|
|
||||||
preFilter.setOrder(preFilter.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
return new DeferringMethodInterceptor<>(preFilter, (f) -> {
|
|
||||||
templateExpressionDefaultsProvider.ifAvailable(f::setTemplateDefaults);
|
|
||||||
methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
|
|
||||||
f.setExpressionHandler(expressionHandlerProvider
|
|
||||||
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
|
|
||||||
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
|
static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
ObjectProvider<PrePostMethodSecurityConfiguration> _prePostMethodSecurityConfiguration) {
|
||||||
ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
|
return new DeferringMethodInterceptor<>(preAuthorizePointcut,
|
||||||
ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
|
() -> _prePostMethodSecurityConfiguration.getObject().preAuthorizeMethodInterceptor);
|
||||||
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
|
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
|
||||||
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
|
|
||||||
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
|
|
||||||
PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
|
|
||||||
PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
|
|
||||||
manager.setApplicationContext(context);
|
|
||||||
AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor
|
|
||||||
.preAuthorize(manager(manager, registryProvider));
|
|
||||||
preAuthorize.setOrder(preAuthorize.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
return new DeferringMethodInterceptor<>(preAuthorize, (f) -> {
|
|
||||||
templateExpressionDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
|
|
||||||
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
|
|
||||||
manager.setExpressionHandler(expressionHandlerProvider
|
|
||||||
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
|
|
||||||
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
|
|
||||||
eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
|
static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
ObjectProvider<PrePostMethodSecurityConfiguration> _prePostMethodSecurityConfiguration) {
|
||||||
ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
|
return new DeferringMethodInterceptor<>(postAuthorizePointcut,
|
||||||
ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
|
() -> _prePostMethodSecurityConfiguration.getObject().postAuthorizeMethodInterceptor);
|
||||||
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
|
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
|
||||||
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
|
|
||||||
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
|
|
||||||
PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
|
|
||||||
PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
|
|
||||||
manager.setApplicationContext(context);
|
|
||||||
AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor
|
|
||||||
.postAuthorize(manager(manager, registryProvider));
|
|
||||||
postAuthorize.setOrder(postAuthorize.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
return new DeferringMethodInterceptor<>(postAuthorize, (f) -> {
|
|
||||||
templateExpressionDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
|
|
||||||
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
|
|
||||||
manager.setExpressionHandler(expressionHandlerProvider
|
|
||||||
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
|
|
||||||
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
|
|
||||||
eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor postFilterAuthorizationMethodInterceptor(
|
static MethodInterceptor postFilterAuthorizationMethodInterceptor(
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
ObjectProvider<PrePostMethodSecurityConfiguration> _prePostMethodSecurityConfiguration) {
|
||||||
ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
|
return new DeferringMethodInterceptor<>(postFilterPointcut,
|
||||||
ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
|
() -> _prePostMethodSecurityConfiguration.getObject().postFilterMethodInterceptor);
|
||||||
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
|
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
|
||||||
ObjectProvider<RoleHierarchy> roleHierarchyProvider, PrePostMethodSecurityConfiguration configuration,
|
|
||||||
ApplicationContext context) {
|
|
||||||
PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
|
|
||||||
postFilter.setOrder(postFilter.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
return new DeferringMethodInterceptor<>(postFilter, (f) -> {
|
|
||||||
templateExpressionDefaultsProvider.ifAvailable(f::setTemplateDefaults);
|
|
||||||
methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
|
|
||||||
f.setExpressionHandler(expressionHandlerProvider
|
|
||||||
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
|
|
||||||
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MethodSecurityExpressionHandler defaultExpressionHandler(
|
|
||||||
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
|
|
||||||
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext context) {
|
|
||||||
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
|
|
||||||
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
|
|
||||||
handler.setRoleHierarchy(roleHierarchy);
|
|
||||||
defaultsProvider.ifAvailable((d) -> handler.setDefaultRolePrefix(d.getRolePrefix()));
|
|
||||||
handler.setApplicationContext(context);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
static <T> AuthorizationManager<T> manager(AuthorizationManager<T> delegate,
|
|
||||||
ObjectProvider<ObservationRegistry> registryProvider) {
|
|
||||||
return new DeferringObservationAuthorizationManager<>(registryProvider, delegate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||||
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
||||||
this.interceptorOrderOffset = annotation.offset();
|
this.preFilterMethodInterceptor.setOrder(this.preFilterMethodInterceptor.getOrder() + annotation.offset());
|
||||||
}
|
this.preAuthorizeMethodInterceptor
|
||||||
|
.setOrder(this.preAuthorizeMethodInterceptor.getOrder() + annotation.offset());
|
||||||
private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
|
this.postAuthorizeMethodInterceptor
|
||||||
implements AuthorizationAdvisor {
|
.setOrder(this.postAuthorizeMethodInterceptor.getOrder() + annotation.offset());
|
||||||
|
this.postFilterMethodInterceptor.setOrder(this.postFilterMethodInterceptor.getOrder() + annotation.offset());
|
||||||
private final Pointcut pointcut;
|
|
||||||
|
|
||||||
private final int order;
|
|
||||||
|
|
||||||
private final Supplier<M> delegate;
|
|
||||||
|
|
||||||
DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
|
|
||||||
this.pointcut = delegate.getPointcut();
|
|
||||||
this.order = delegate.getOrder();
|
|
||||||
this.delegate = SingletonSupplier.of(() -> {
|
|
||||||
supplier.accept(delegate);
|
|
||||||
return delegate;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
|
||||||
return this.delegate.get().invoke(invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pointcut getPointcut() {
|
|
||||||
return this.pointcut;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Advice getAdvice() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOrder() {
|
|
||||||
return this.order;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPerInstance() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,16 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
|
||||||
|
import org.springframework.aop.Pointcut;
|
||||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -29,14 +33,13 @@ import org.springframework.context.annotation.ImportAware;
|
|||||||
import org.springframework.context.annotation.Role;
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.security.access.annotation.Secured;
|
import org.springframework.security.access.annotation.Secured;
|
||||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
|
||||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||||
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
|
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
|
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
|
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,40 +50,59 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|||||||
* @since 5.6
|
* @since 5.6
|
||||||
* @see EnableMethodSecurity
|
* @see EnableMethodSecurity
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(value = "_securedMethodSecurityConfiguration", proxyBeanMethods = false)
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
final class SecuredMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
|
final class SecuredMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
|
||||||
|
|
||||||
private int interceptorOrderOffset;
|
private static final Pointcut pointcut = AuthorizationManagerBeforeMethodInterceptor.secured().getPointcut();
|
||||||
|
|
||||||
|
private final SecuredAuthorizationManager authorizationManager = new SecuredAuthorizationManager();
|
||||||
|
|
||||||
|
private AuthorizationManagerBeforeMethodInterceptor methodInterceptor = AuthorizationManagerBeforeMethodInterceptor
|
||||||
|
.secured(this.authorizationManager);
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
static MethodInterceptor securedAuthorizationMethodInterceptor(
|
static MethodInterceptor securedAuthorizationMethodInterceptor(
|
||||||
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
|
ObjectProvider<SecuredMethodSecurityConfiguration> securedMethodSecurityConfiguration) {
|
||||||
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
|
Supplier<AuthorizationManagerBeforeMethodInterceptor> supplier = () -> {
|
||||||
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
|
SecuredMethodSecurityConfiguration configuration = securedMethodSecurityConfiguration.getObject();
|
||||||
SecuredMethodSecurityConfiguration configuration) {
|
return configuration.methodInterceptor;
|
||||||
SecuredAuthorizationManager secured = new SecuredAuthorizationManager();
|
};
|
||||||
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
|
return new DeferringMethodInterceptor<>(pointcut, supplier);
|
||||||
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
|
|
||||||
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
|
|
||||||
secured.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
|
|
||||||
SecurityContextHolderStrategy strategy = strategyProvider
|
|
||||||
.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
|
|
||||||
AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(
|
|
||||||
registryProvider, secured);
|
|
||||||
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
|
|
||||||
.secured(manager);
|
|
||||||
interceptor.setOrder(interceptor.getOrder() + configuration.interceptorOrderOffset);
|
|
||||||
interceptor.setSecurityContextHolderStrategy(strategy);
|
|
||||||
eventPublisherProvider.ifAvailable(interceptor::setAuthorizationEventPublisher);
|
|
||||||
return interceptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||||
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
|
||||||
this.interceptorOrderOffset = annotation.offset();
|
this.methodInterceptor.setOrder(this.methodInterceptor.getOrder() + annotation.offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||||
|
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
|
||||||
|
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
|
||||||
|
this.authorizationManager.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||||
|
this.methodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setObservationRegistry(ObservationRegistry registry) {
|
||||||
|
if (registry.isNoop()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AuthorizationManager<MethodInvocation> observed = new ObservationAuthorizationManager<>(registry,
|
||||||
|
this.authorizationManager);
|
||||||
|
this.methodInterceptor = AuthorizationManagerBeforeMethodInterceptor.secured(observed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
void setEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
||||||
|
this.methodInterceptor.setAuthorizationEventPublisher(eventPublisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,13 @@ import org.junit.jupiter.params.ParameterizedTest;
|
|||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.aop.Advisor;
|
||||||
|
import org.springframework.aop.config.AopConfigUtils;
|
||||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||||
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||||
import org.springframework.context.annotation.AdviceMode;
|
import org.springframework.context.annotation.AdviceMode;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -65,6 +68,7 @@ import org.springframework.security.access.prepost.PreFilter;
|
|||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
|
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory.TargetVisitor;
|
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory.TargetVisitor;
|
||||||
import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
|
import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
|
||||||
@ -85,6 +89,7 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|||||||
import org.springframework.security.test.context.support.WithAnonymousUser;
|
import org.springframework.security.test.context.support.WithAnonymousUser;
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
|
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.TestExecutionListeners;
|
import org.springframework.test.context.TestExecutionListeners;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
@ -964,6 +969,32 @@ public class PrePostMethodSecurityConfigurationTests {
|
|||||||
this.spring.getContext().getBean(ClassInheritingAbstractClassWithNoAnnotations.class).method();
|
this.spring.getContext().getBean(ClassInheritingAbstractClassWithNoAnnotations.class).method();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-15592
|
||||||
|
@Test
|
||||||
|
void autowireWhenDefaultsThenCreatesExactlyOneAdvisorPerAnnotation() {
|
||||||
|
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
||||||
|
AuthorizationAdvisorProxyFactory proxyFactory = this.spring.getContext()
|
||||||
|
.getBean(AuthorizationAdvisorProxyFactory.class);
|
||||||
|
assertThat(proxyFactory).hasSize(5);
|
||||||
|
assertThat(this.spring.getContext().getBeanNamesForType(AuthorizationAdvisor.class)).hasSize(5)
|
||||||
|
.containsExactlyInAnyOrder("preFilterAuthorizationMethodInterceptor",
|
||||||
|
"preAuthorizeAuthorizationMethodInterceptor", "postAuthorizeAuthorizationMethodInterceptor",
|
||||||
|
"postFilterAuthorizationMethodInterceptor", "authorizeReturnObjectMethodInterceptor");
|
||||||
|
}
|
||||||
|
|
||||||
|
// gh-15592
|
||||||
|
@Test
|
||||||
|
void autowireWhenAspectJAutoProxyAndFactoryBeanThenExactlyOneAdvisorPerAnnotation() {
|
||||||
|
this.spring.register(AspectJAwareAutoProxyAndFactoryBeansConfig.class).autowire();
|
||||||
|
AuthorizationAdvisorProxyFactory proxyFactory = this.spring.getContext()
|
||||||
|
.getBean(AuthorizationAdvisorProxyFactory.class);
|
||||||
|
assertThat(proxyFactory).hasSize(5);
|
||||||
|
assertThat(this.spring.getContext().getBeanNamesForType(AuthorizationAdvisor.class)).hasSize(5)
|
||||||
|
.containsExactlyInAnyOrder("preFilterAuthorizationMethodInterceptor",
|
||||||
|
"preAuthorizeAuthorizationMethodInterceptor", "postAuthorizeAuthorizationMethodInterceptor",
|
||||||
|
"postFilterAuthorizationMethodInterceptor", "authorizeReturnObjectMethodInterceptor");
|
||||||
|
}
|
||||||
|
|
||||||
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
|
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
|
||||||
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
|
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
|
||||||
}
|
}
|
||||||
@ -1541,4 +1572,30 @@ public class PrePostMethodSecurityConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableMethodSecurity
|
||||||
|
static class AspectJAwareAutoProxyAndFactoryBeansConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
static BeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor() {
|
||||||
|
return AopConfigUtils::registerAspectJAnnotationAutoProxyCreatorIfNecessary;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component
|
||||||
|
static class MyFactoryBean implements FactoryBean<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject() throws Exception {
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getObjectType() {
|
||||||
|
return Object.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user