2016-06-30 17 views
1

Ich habe ein Problem mit einem Ressourcenserver mit Spring Cloud und Spring OAuth2. Ich habe eine vorzuauthorisieren Anmerkung auf einer Methode, die ich schützen wollen, aber der oauth2 Ausdruck wird der normale Ausdrücke (hasRole) funktionieren ignoriert:Spring Cloud & Spring OAuth2 - EnableGlobalMethodSecurity löst AlreadyBuiltException

@SpringBootApplication 
@RestController 
public class ResourceServiceApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(ResourceServiceApplication.class, args); 
    } 

    @RequestMapping("/") 
    @PreAuthorize("#oauth2.hasScope('nothing')") 
    public Message home(OAuth2Authentication principal) { 
     return new Message("Hello World"); 
    } 

    class Message { 
     private String id = UUID.randomUUID().toString(); 
     private String content; 

     Message() {} 

     public Message(String content) { 
      this.content = content; 
     } 

     public String getId() { 
      return id; 
     } 

     public String getContent() { 
      return content; 
     } 
    } 

} 

Ich versuchte, die OAuth2 Ausdrücke in meiner Konfiguration Klasse zu ermöglichen, etwa so:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@EnableResourceServer 
public class ApplicationConfiguration extends GlobalMethodSecurityConfiguration { 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     return new OAuth2MethodSecurityExpressionHandler(); 
    } 

} 

jedoch die EnableGlobalMethodSecurity (prePostEnabled = true) wirft die folgende Ausnahme:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceServiceApplication': Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Unexpected AOP exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE] 
    at io.myapp.ResourceServiceApplication.main(ResourceServiceApplication.java:21) [main/:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_77] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_77] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_77] 
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_77] 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na] 
Caused by: org.springframework.aop.framework.AopConfigException: Unexpected AOP exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:219) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:468) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    ... 20 common frames omitted 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor.getAdvice(MethodSecurityMetadataSourceAdvisor.java:107) ~[spring-security-core-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.aop.framework.CglibAopProxy$ProxyCallbackFilter.hashCode(CglibAopProxy.java:941) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.cglib.core.WeakCacheKey.<init>(WeakCacheKey.java:19) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:426) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:338) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:203) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    ... 27 common frames omitted 
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    ... 42 common frames omitted 
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built 
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:44) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManager(AuthenticationConfiguration.java:81) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration.authenticationManager(GlobalMethodSecurityConfiguration.java:257) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration.methodSecurityInterceptor(GlobalMethodSecurityConfiguration.java:123) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration$$EnhancerBySpringCGLIB$$d6e529d.CGLIB$methodSecurityInterceptor$0(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration$$EnhancerBySpringCGLIB$$d6e529d$$FastClassBySpringCGLIB$$3f6571c9.invoke(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration$$EnhancerBySpringCGLIB$$d6e529d.methodSecurityInterceptor(<generated>) ~[spring-security-config-4.0.4.RELEASE.jar:4.0.4.RELEASE] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_77] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_77] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_77] 
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_77] 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    ... 43 common frames omitted 

Wenn ich die prePostEnabled p entfernen arameter, es wird kein Fehler ausgegeben, aber die Ausdrücke sind nicht aktiviert. Hier ist die Gradle-Datei für die Anwendung:

buildscript { 
    ext { 
     springBootVersion = '1.4.0.M3' 
    } 
    repositories { 
     mavenCentral() 
     maven { url "https://repo.spring.io/snapshot" } 
     maven { url "https://repo.spring.io/milestone" } 
    } 
    dependencies { 
     classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
    } 
} 

apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'spring-boot' 

jar { 
    baseName = 'resource-service' 
    version = '0.0.1-SNAPSHOT' 
} 
sourceCompatibility = 1.8 
targetCompatibility = 1.8 

repositories { 
    mavenCentral() 
    maven { url "https://repo.spring.io/snapshot" } 
    maven { url "https://repo.spring.io/milestone" } 
} 


dependencies { 
    compile('org.springframework.boot:spring-boot-starter-web') 
    compile('org.springframework.boot:spring-boot-starter-security') 
    compile('org.springframework.security.oauth:spring-security-oauth2') 
    testCompile('org.springframework.boot:spring-boot-starter-test') 
    compile('org.springframework.cloud:spring-cloud-starter-oauth2') 
} 

dependencyManagement { 
    imports { 
     mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Brixton.SR1" 
    } 
} 

eclipse { 
    classpath { 
     containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') 
     containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' 
    } 
} 

Jede Hilfe wird sehr geschätzt.

Antwort

1

Wenn Sie den @RestController Teil des Codes an einen anderen unabhängigen Klasse bewegen sollte der Fehler weggehen - das ist eine gute Praxis, auch wie in Ihrem Beispiel die Konfiguration und eine Gewebeschicht werden miteinander vermischt:

@RestController 
public class TestController { 
    @RequestMapping("/") 
    @PreAuthorize("#oauth2.hasScope('nothing')") 
    public Message home(OAuth2Authentication principal) { 
     return new Message("Hello World"); 
    } 

    class Message { 
     private String id = UUID.randomUUID().toString(); 
     private String content; 

     Message() {} 

     public Message(String content) { 
      this.content = content; 
     } 

     public String getId() { 
      return id; 
     } 

     public String getContent() { 
      return content; 
     } 
    } 
} 

Was wahrscheinlich passiert ist, dass einen CGLIB-Proxy erstellt und Spring Security zusätzlich auch Proxies erstellt, um den Methodenaufruf abzufangen, und diese beiden funktionieren nicht gut miteinander. Durch die Trennung wird das Problem gemildert.

+0

Das hat es behoben! Ich bin immer noch nicht an Anmerkungen gewöhnt, die so viel machen, also habe ich am Ende die ganze Sache mit dem Prinzip der einzigen Verantwortung ausgelöscht. Vielen Dank! – StylePotato