Make sure bean resolver is set in the OAuth2 expression evaluator

Also copies the ExpressionParser (the only public getter), trust
resolver and permission evaluator (if available in the context). Changes
the logic to not replace an existing OAuth2MethodSecurityExpressionHandler
so that users can override simply by providing a bean of that type.

Fixes gh-3542
This commit is contained in:
Dave Syer 2015-07-20 14:12:48 +01:00
parent c181a2d157
commit c5008f844c
1 changed files with 51 additions and 4 deletions

View File

@ -17,13 +17,18 @@
package org.springframework.boot.autoconfigure.security.oauth2.method; package org.springframework.boot.autoconfigure.security.oauth2.method;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler; import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
@ -39,18 +44,35 @@ import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecur
@Configuration @Configuration
@ConditionalOnClass({ OAuth2AccessToken.class }) @ConditionalOnClass({ OAuth2AccessToken.class })
@ConditionalOnBean(GlobalMethodSecurityConfiguration.class) @ConditionalOnBean(GlobalMethodSecurityConfiguration.class)
public class OAuth2MethodSecurityConfiguration implements BeanFactoryPostProcessor { public class OAuth2MethodSecurityConfiguration implements BeanFactoryPostProcessor,
ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException { throws BeansException {
OAuth2ExpressionHandlerInjectionPostProcessor processor = new OAuth2ExpressionHandlerInjectionPostProcessor(); OAuth2ExpressionHandlerInjectionPostProcessor processor = new OAuth2ExpressionHandlerInjectionPostProcessor(
this.applicationContext);
beanFactory.addBeanPostProcessor(processor); beanFactory.addBeanPostProcessor(processor);
} }
private static class OAuth2ExpressionHandlerInjectionPostProcessor implements private static class OAuth2ExpressionHandlerInjectionPostProcessor implements
BeanPostProcessor { BeanPostProcessor {
private ApplicationContext applicationContext;
public OAuth2ExpressionHandlerInjectionPostProcessor(
ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException { throws BeansException {
@ -60,11 +82,36 @@ public class OAuth2MethodSecurityConfiguration implements BeanFactoryPostProcess
@Override @Override
public Object postProcessAfterInitialization(Object bean, String beanName) public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException { throws BeansException {
if (bean instanceof DefaultMethodSecurityExpressionHandler) { if (bean instanceof DefaultMethodSecurityExpressionHandler
return new OAuth2MethodSecurityExpressionHandler(); && !(bean instanceof OAuth2MethodSecurityExpressionHandler)) {
return getExpressionHandler((DefaultMethodSecurityExpressionHandler) bean);
} }
return bean; return bean;
} }
private OAuth2MethodSecurityExpressionHandler getExpressionHandler(
DefaultMethodSecurityExpressionHandler bean) {
OAuth2MethodSecurityExpressionHandler handler = new OAuth2MethodSecurityExpressionHandler();
handler.setApplicationContext(this.applicationContext);
AuthenticationTrustResolver trustResolver = findInContext(AuthenticationTrustResolver.class);
if (trustResolver != null) {
handler.setTrustResolver(trustResolver);
}
PermissionEvaluator permissions = findInContext(PermissionEvaluator.class);
if (permissions != null) {
handler.setPermissionEvaluator(permissions);
}
handler.setExpressionParser(bean.getExpressionParser());
return handler;
}
private <T> T findInContext(Class<T> type) {
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.applicationContext, type).length == 1) {
return this.applicationContext.getBean(type);
}
return null;
}
} }
} }