1

我正在使用 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 配置,但我无法在文档中的任何地方找到该配置。

4

3 回答 3

1

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

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

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

于 2012-08-06T12:01:47.100 回答
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> 

服务的上下文文件。 服务.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"/>
于 2012-08-23T11:07:16.833 回答
0

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

所以只能java.lang.reflect.Proxy使用,因此不可能代理私有方法!只需@Secured公开方法 - 一切都会好起来的!

于 2014-12-15T18:27:01.417 回答