AOP MethodSecurityInterceptor未在Spring Security中调用

时间:2012-07-30 05:08:42

标签: spring spring-security spring-aop

我正在使用Spring Security 3.0.7,我的应用程序部署在JBOSS上。

我正在为我的应用程序设置 org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor ,以添加对服务层中某些方法的调用的限制。但由于某种原因拦截器没有被调用,我能够从具有角色 ROLE_USER 的用户调用所有方法。 我的security.xml看起来像这样:

<security:http auto-config='true' authentication-manager-ref="authenticationManager" use-expressions="true" request-matcher="ant" create-session="always"
    entry-point-ref="authenticationEntryPoint" >

    <security:intercept-url pattern="/login.jsp" access="permitAll" />
    <security:intercept-url pattern="/configure/" access="hasRole('ROLE_ADMIN')"  />
    <security:intercept-url pattern="/**" access="isAuthenticated()" />

    <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=Authentication Failed!" default-target-url="/landing.do" 
    always-use-default-target="true"  />

    <security:logout invalidate-session="true" delete-cookies="true" />


    <security:session-management>
        <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.jsp"/>
    </security:session-management>    
</security:http>

<security:method-security-metadata-source id="securityMetadataSource">
        <security:protect method="com.services.CreateUserService.createUser" access="ROLE_ADMIN"/>
        <security:protect method="com.services.DeleteUser.deleteUser" access="ROLE_ADMIN"/>
</security:method-security-metadata-source>

<security:global-method-security authentication-manager-ref="authenticationManager" access-decision-manager-ref="accessDecisionManager" 
metadata-source-ref="securityMetadataSource" pre-post-annotations="disabled" secured-annotations="disabled" />

<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <property name="loginFormUrl" value="/login.jsp"/>
</bean>

<bean id="myRoleVoter" class="com.interceptors.MyRoleVoter" />

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
    <property name="providers">
        <list>
            <ref local="daoAuthenticationProvider"/>
        </list>
    </property>
</bean> 

<bean id="accessDecisionManager" class="com.interceptors.MyAccessDecisionManager"  p:allowIfAllAbstainDecisions="false" >
    <property name="decisionVoters">
        <list>
            <ref local="myRoleVoter"/>
        </list>
    </property> 
</bean>


<bean id="methodSecurity" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager" ref="accessDecisionManager"/>
        <property name="securityMetadataSource" ref="securityMetadataSource" />
</bean> 

认证部分工作正常。但是,我的MethodSecurityInterceptor从不被调用,因此甚至不是我的AccessDecisionManager或RoleVoter。

如果我在第一行添加了accessDecisionManager的引用,那么我的身份验证层就会停止工作。所有请求都以匿名用户身份传递给AccessDecisionManager。

<security:http security="none" pattern="/login.jsp" />

<security:http auto-config='true' authentication-manager-ref="authenticationManager" access-decision-manager-ref="accessDecisionManager" use-expressions="true" request-matcher="ant" create-session="always"
    entry-point-ref="authenticationEntryPoint" >

我知道我缺少一些TINY配置,但我无法在文档中的任何位置找到该配置。

3 个答案:

答案 0 :(得分:1)

可能,您已在应用程序根上下文中声明了MethodSecurityInterceptor,并期望它适用于servlet上下文中的bean。

如果希望global-method-security在servlet上下文中工作,则应在servlet xml配置中明确声明它。

在错误的上下文中声明AOP拦截器是一个非常常见的错误,因此请检查在servlet上下文中是否未创建服务层bean(例如通过自动扫描)。

答案 1 :(得分:1)

我已经找到了解决方案。我必须定义两个身份验证管理器和一个访问决策管理器。一个身份验证管理器进入我的根上下文,全局方法安全性将使用它来创建表单登录身份验证机制。

另一个身份验证管理器和访问决策管理器进入服务上下文,在那里它将用于创建我的自定义方法安全拦截器。

<强>的applicationContext-security.xml文件

<!-- The authentication manager responsible for authenticating the users -->
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
    <property name="providers">
        <list>
            <ref local="daoAuthenticationProvider"/>
        </list>
    </property>
</bean> 

   

服务的上下文文件。 的 service.security.xml

                                                 

    <!--we need a separate authentication manager for method security -->
    <bean id="methodAuthenticationManager" class="org.springframework.security.authentication.ProviderManager" >
        <property name="providers">
            <list>
                <ref local="daoAuthenticationProvider"/>
            </list>
        </property>
    </bean> 

    <!--we need a separate accessDecisionManager for method security -->
    <bean id="methodAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased" >
        <property name="decisionVoters">
            <list>
                <ref local="myRoleVoter"/> <!-- the voter will decide weather methodInvocation is allowed or not -->
            </list>
        </property> 
    </bean>

    <!-- The Method Security Interceptor to intercept all the calls to methods -->
    <bean id="methodSecurityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
        <property name="authenticationManager" ref="methodAuthenticationManager"/>
        <property name="accessDecisionManager" ref="methodAccessDecisionManager"/>
        <property name="securityMetadataSource" ref="swiftSecurityMethodMetadataSource" />
    </bean>


<security:method-security-metadata-source id="securityMetadataSource">
    <security:protect method="fullyQualifiedMethod" access="Administrator"/>
</security:method-security-metadata-source>

<security:global-method-security authentication-manager-ref="methodAuthenticationManager" access-decision-manager-ref="methodAccessDecisionManager" 
    metadata-source-ref="swiftSecurityMethodMetadataSource" jsr250-annotations="disabled" secured-annotations="disabled"/>

答案 2 :(得分:0)

未调用AOP MethodSecurityInterceptor的另一个常见原因 - 您错过cglib或类似字节代码操作。

因此仅使用java.lang.reflect.Proxy,因此无法代理私有方法!只需公开@Secured个方法 - 一切都很好!