我正在使用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配置,但我无法在文档中的任何位置找到该配置。
答案 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
个方法 - 一切都很好!