SEC-1455: SecurityNamespaceHandler problems in OSGi environment, need to import spring-security-web packages #1695

Closed
spring-issuemaster opened this Issue Apr 6, 2010 · 6 comments

1 participant

@spring-issuemaster

Daniël van 't Ooster (Migrated from SEC-1455) said:

Imagine the following situation: there is an OSGi (in my case DM Server) environment, which contains some bundles. One of them uses the security namespace to protect some methods. This bundle has nothing to do with the web, this is the responsibility of the web bundle, which contains some web pages and expose some of the services from that bundle. . Within the web bundle, a filter-chain-map is used to protect some URLs.

The manifest of the first bundle imports some Spring Security related packages, but not org.springframework.security.web, this package is only imported by the web bundle. The SecurityNamespaceHandler seems to be a singleton, and when the org.springframework.security.web.FilterChainProxy is not available on the classpath when the SecurityNamespaceHandler is loaded for the first time (in my case, when the first bundle is started), an exception will be thrown when another bundle is using the security:http and security:filter-chain-map elements.

Workaround:
Import the org.springframework.security.web package in all bundles which do something with the security namespace.

Stacktrace:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: spring-security-web classes are not available. You need these to use
Offending resource: URL [bundleentry://121.fwk7527493/WEB-INF/applicationContext.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.fatal(FailFastProblemReporter.java:59)
at org.springframework.beans.factory.parsing.ReaderContext.fatal(ReaderContext.java:68)
at org.springframework.beans.factory.parsing.ReaderContext.fatal(ReaderContext.java:55)
at org.springframework.security.config.SecurityNamespaceHandler.reportMissingWebClasses(SecurityNamespaceHandler.java:91)
at org.springframework.security.config.SecurityNamespaceHandler.decorate(SecurityNamespaceHandler.java:72)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.decorateIfRequired(BeanDefinitionParserDelegate.java:1372)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired(BeanDefinitionParserDelegate.java:1359)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired(BeanDefinitionParserDelegate.java:1339)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition(DefaultBeanDefinitionDocumentReader.java:261)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:154)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:133)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:164)
at org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:136)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:458)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:69)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:269)
at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:247)
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:214)
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:169)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:175)
at org.springframework.osgi.extender.internal.activator.ContextLoaderListener$2.run(ContextLoaderListener.java:716)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.osgi.extender.internal.activator.ContextLoaderListener.maybeCreateApplicationContextFor(ContextLoaderListener.java:781)
at org.springframework.osgi.extender.internal.activator.ContextLoaderListener$ContextBundleListener.handleEvent(ContextLoaderListener.java:229)
at org.springframework.osgi.extender.internal.activator.ContextLoaderListener$BaseListener.bundleChanged(ContextLoaderListener.java:172)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:919)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1350)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1301)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:362)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:280)
at com.springsource.kernel.core.internal.StandardBundleStarter.start(StandardBundleStarter.java:68)
at com.springsource.kernel.core.internal.StandardBundleStarter.start(StandardBundleStarter.java:56)
at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy60.start(Unknown Source)
at com.springsource.kernel.install.artifact.internal.bundle.StandardBundleDriver.startBundle(StandardBundleDriver.java:177)
at com.springsource.kernel.install.artifact.internal.bundle.StandardBundleDriver.start(StandardBundleDriver.java:158)
at com.springsource.kernel.install.artifact.internal.bundle.StandardBundleInstallArtifact.doStart(StandardBundleInstallArtifact.java:262)
at com.springsource.kernel.install.artifact.internal.AbstractInstallArtifact.driveDoStart(AbstractInstallArtifact.java:211)
at com.springsource.kernel.install.artifact.internal.bundle.StandardBundleInstallArtifact.start(StandardBundleInstallArtifact.java:251)
at com.springsource.kernel.deployer.core.internal.PipelinedApplicationDeployer.start(PipelinedApplicationDeployer.java:291)
at com.springsource.kernel.deployer.core.internal.PipelinedApplicationDeployer.deploy(PipelinedApplicationDeployer.java:201)
at com.springsource.kernel.deployer.management.StandardDeployer.deploy(StandardDeployer.java:62)
at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.jmx.mbeanserver.ConvertingMethod.invokeWithOpenReturn(ConvertingMethod.java:167)
at com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(MXBeanIntrospector.java:96)
at com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(MXBeanIntrospector.java:33)
at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:208)
at com.sun.jmx.mbeanserver.PerInterface.invoke(PerInterface.java:120)
at com.sun.jmx.mbeanserver.MBeanSupport.invoke(MBeanSupport.java:262)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1426)
at javax.management.remote.rmi.RMIConnectionImpl.access$200(RMIConnectionImpl.java:72)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1264)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1359)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:788)
at sun.reflect.GeneratedMethodAccessor87.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)

@spring-issuemaster

Luke Taylor said:

Could you clarify the version you are using, please. You say SFW 3.0.0. Do you mean Spring Security? If so, could you check with the latest version? If there are still could you possibly supply a test app which reproduces the issue?

@spring-issuemaster

Daniël van 't Ooster said:

Hi Luke,

see the attached jars or eclipse projects.

They are tested on dm server 2.0.1 with spring security 3.0.0. First start bundle1 which will create an instance of the security namespace handler. After that, start bundle2, it will give the problem as described in the case. Imho the problematic code is in the SecurityNamespaceHandler:

    // Web-namespace stuff
    if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", ClassUtils.getDefaultClassLoader())) {
        parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
        parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
        parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
        filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
        //registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
    }
}

Because this is a singleton and the org.springframework.security.web class it not imported in bundle1 (imaging bundle1 has nothing to do with the web), the handler cannot handle the http related elements.

Grtz,
Daniël

@spring-issuemaster

Christopher Frost said:

Daniel,

Luke has asked me to look at this as I work on dm Server and will have a little more insight from that point of view, I haven't managed to get to it today but I understand the issue. I need to recreate it and have a look myself, will do so next week.
I am tracking this from my own project with https://issuetracker.springsource.com/browse/DMS-2551.

Chris

@spring-issuemaster

Christopher Frost said:

Hi,

I've looked in to this and tried deploying you test bundles with different headers. Your diagnoses is correct, because the SecurityNamespaceHandler is a singleton and the way it loads the web stuff if you want to use the web elements anywhere in an instance of the dm Server then the first bundle loaded that uses security must import the security web bundle, bundles after that don't matter. This should not impact what you need to have deployed as the security.web bundle is required by the security.config bundle anyway. This is far from ideal though, having to have this unintuitive import but from OSGi's point of view it is working as intended. This isn't even a dm Server issue, it's fundamental OSGi. A better solution to get around the singleton issue would be to make the code in the security.config bundle a little smarter about OSGi, as it imports the security.web bundle anyway I would want this 'if statement' to always return true in an OSGi environment, i.e. be aware of the OSGi classloader system.

Luke, please ping me if you want to discuss...

Chris.

P.S. Thanks for the well cut-down test bundles, made recreating it a breeze.

@spring-issuemaster

Luke Taylor said:

Apparently dmServer has some specialized internal behaviour related to classloading and namespace-handling (bundles which contain spring.schemas files), so this may account for why the web classes are not visible, even though they are declared in the config bundle. I have altered the code to attempt to load the parsers when they are required, rather than just when the init() method is called (which presumably only happens the first time the class is registered). This appears to solve the problem, though the second test bundle fails to deploy because it doesn't import the package that contains BasicAuthenticationFilter. Adding the import solves that problem too.

@spring-issuemaster

Luke Taylor said:

Resolving, as the above change seems to fix the problem.

@spring-issuemaster spring-issuemaster added this to the 3.1.0.M1 milestone Feb 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment