Spring Security and OSGi

eclipse-virgo, osgi, spring-security

Solution

This looks like a bug to me. Line 386 of the file GlobalMethodSecurityBeanDefinitionParser.java that raises the error is

delegate = beanFactory.getBean(authMgrBean, ProviderManager.class);

It asks the bean factory for an bean with the concrete implementation `ProviderManager`, but it should only request a bean with the interface `AuthenticationManager` like:

delegate = beanFactory.getBean(authMgrBean, AuthenticationManager.class);

You may want to raise a ticket in Spring Security's Jira.

BTW: We are also exporting the authenticationManager as an OSGI service and consume it in other bundles, which works really well.

Problem

I am trying to create a simple example using Spring Security 3.1.3 on Virgo 3.6.0.M03. The example consists of 3 bundles: security bundle configuring and publishing an AuthenticationManager ``` <security:authentication-manager id="authenticationManager"> <security:authentication-provider> <security:user-service> <security:user name="Rigas" password="password" authorities="ROLE_MEMBER"/> </security:user-service> </security:authentication-provider> </security:authentication-manager> <service id="authenticationManagerOsgi" ref="authenticationManager" interface="org.springframework.security.authentication.AuthenticationManager"/> ``` helloSecurity bundle publishing a secured helloWorld method. It references the AuthenticationManager and injects it in global-method-security. ``` <security:global-method-security secured-annotations="enabled" authentication-manager-ref="authenticationManager"/> <reference id="authenticationManager" availability="mandatory" interface="org.springframework.security.authentication.AuthenticationManager"/> <service id="helloSpringSecurityOsgi" ref="helloSpringSecurity" interface="net.ansible.examples.hellospringsecurity.HelloSpringSecurity" /> ``` helloSecurityConsumer bundle referencing the helloSecurity IF and calling the secured helloWorld method. ``` <reference id="helloSpringSecurity" availability="mandatory" interface="net.ansible.examples.hellospringsecurity.HelloSpringSecurity"/> ``` Bundle statup and wiring work properly, but once helloSecurityConsumer calls the secured method the following exception is thrown: ``` Failed to call secure method org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'authenticationManager' must be of type [org.springframework.security.authentication.ProviderManager], but was actually of type [$Proxy94] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:360) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser$AuthenticationManagerDelegator.authenticate(GlobalMethodSecurityBeanDefinitionParser.java:386) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.authenticateIfRequired(AbstractSecurityInterceptor.java:316) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:202) at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) at net.ansible.examples.hellospringsecurity.impl.HelloSpringSecurityImpl$$EnhancerByCGLIB$$99e49c75.sayHello(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319) at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) 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.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) 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 $Proxy95.sayHello(Unknown Source) at net.ansible.examples.hellospringsecurityconsumer.impl.HelloSpringSecurityConsumerImpl$MyRunnable.run(HelloSpringSecurityConsumerImpl.java:50) at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(Unknown Source) at java.util.concurrent.FutureTask.runAndReset(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) ``` GlobalMethodSecurityBeanDefinitionParser attempts to use the referenced AuthenticationManager and has a problem converting the Proxy around the OSGi refeternce to a ProviderManager. Debugging shows the Proxy (a jdkDynamicAopProxy) is indeed a proxy around the ProviderManager class and has all the relevant interfaces. Is there a working configuration to achieve what I am trying to do?

Original source