2012-07-30 104 views
1

我使用的是Spring Security 3.0.7,我的應用程序部署在JBOSS上。AOP MethodSecurityInterceptor未在Spring Security中調用

我爲我的應用程序上的服務層的某些方法的調用添加限制設置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配置,但我無法在文檔中的任何位置找到該配置。

回答

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"/> 
1

可能地,您已在您的應用程序根上下文中聲明您的MethodSecurityInterceptor,並期望它在servlet上下文中爲bean工作。

如果您想global-method-security在servlet上下文中工作,您應該在servlet xml配置中顯式聲明它。

在錯誤的上下文中聲明AOP攔截器是一種非常常見的錯誤,因此請檢查servlet上下文中是否未創建服務層bean(例如,通過自動掃描)。

0

的另一個常見原因爲什麼AOP MethodSecurityInterceptor,則不會調用 - 你錯過cglib或字節代碼相似的操作。

所以只有java.lang.reflect.Proxy使用,因此它是不可能代理私人方法!只要讓@Secured方法公開 - 一切都好!