【问题标题】:Spring Security and OSGiSpring Security 和 OSGi
【发布时间】:2012-11-28 19:03:55
【问题描述】:

我正在尝试在 Virgo 3.6.0.M03 上使用 Spring Security 3.1.3 创建一个简单的示例。 该示例由 3 个捆绑包组成:

  • 配置和发布 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 包发布了一个安全的 helloWorld 方法。它引用 AuthenticationManager 并将其注入到 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 包引用 helloSecurity IF 并调用安全的 helloWorld 方法。

    <reference id="helloSpringSecurity" availability="mandatory" interface="net.ansible.examples.hellospringsecurity.HelloSpringSecurity"/>
    

Bundle statup 和 Wiring 工作正常,但是一旦 helloSecurityConsumer 调用安全方法,就会抛出以下异常:

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 尝试使用引用的 AuthenticationManager,但在将围绕 OSGi 引用的代理转换为 ProviderManager 时遇到问题。 调试显示代理(一个 jdkDynamicAopProxy)确实是 ProviderManager 类周围的代理,并具有所有相关接口。 是否有可行的配置来实现我想要做的事情?

【问题讨论】:

    标签: spring-security osgi eclipse-virgo


    【解决方案1】:

    这对我来说似乎是一个错误。引发错误的文件GlobalMethodSecurityBeanDefinitionParser.java的第386行是

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

    它向 bean factory 请求具有具体实现 ProviderManager 的 bean,但它应该只请求具有接口 AuthenticationManager 的 bean,例如:

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

    您可能想在Spring Security's Jira 提出一张票。

    顺便说一句:我们还将 authenticationManager 导出为 OSGI 服务并在其他捆绑包中使用它,效果非常好。

    【讨论】:

    • 我只记得我不久前打开了一个错误报告,其中有类似的问题:jira.springsource.org/browse/SEC-1842 (forum.springsource.org/showthread.php?116363)。我们还遇到了一个问题,即需要一个 ProviderManager 实例,而不仅仅是一个 AuthenticationManager 实现。所以代码中可能还有其他地方使用了ProviderManager而不是AuthenticationManager。
    • 你是对的。修补 GlobalMethodSecurityBeanDefinitionParser 使一切正常。
    猜你喜欢
    • 2015-06-25
    • 2015-12-08
    • 2015-06-11
    • 2019-07-16
    • 2015-06-09
    • 1970-01-01
    • 2016-03-20
    • 2015-12-10
    • 2012-12-02
    相关资源
    最近更新 更多