@Secured注释工作但@PostAuthorize与PermissionEvaluator没有关系

时间:2012-01-30 16:49:46

标签: spring spring-security

以下问题让我感到疯狂:

我有以下设置:

  • interface StudyService
  • @Service StudyServiceImpl实现了StudyService
  • @Controller StudyServiceController实现StudyService
  • SampleDAOImpl实现SampleDAO
  • permissionEvaluator CdmPermissionEvaluator

我有以下代码:

class SampleDAOImpl implements SampleDAO {
...
    @Secured(Roles.USER)
    @PostAuthorize("hasPermission(returnObject, 'read')")
    Sample load(long sampleId) {
        ...
    }
...
}

@Secured正常工作,因为我必须在存在时登录。但是,即使我注释掉@Secured,@ PostAutorize也不起作用。我在CdmPermissionEvaluator.hasPermission()中有一个日志记录语句,它永远不会被记录。当我注释掉@Secured注释时也是如此(为了避免由于默认的AffirmativeBased选民而未对@PostAuthorize进行评估)。

web.xml的相关部分:

...
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
...
<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.rpc</url-pattern>
</servlet-mapping>
...

spring-servlet.xml的相关部分:

...
<security:global-method-security secured-annotations="enabled"/>
<context:annotation-config/>

<!-- Auto-detect controllers; these extend RemoteServiceServlet and are -->
<!-- annotated with @Controller -->
<context:component-scan base-package="org.gmeb.crf.server">
    <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
...

applicationContext.xml的相关部分:

<context:annotation-config/>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<context:component-scan base-package="org.gmeb.crf">
    <context:exclude-filter type="annotation"
                expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

applicationContext-security.xml的相关部分:

<http auto-config="true" entry-point-ref="authenticationEntryPoint"
      create-session="always" use-expressions="true">
    <intercept-url pattern="/**" access="permitAll()"/>
    <form-login authentication-success-handler-ref="authenticationSuccessHandler"
                authentication-failure-handler-ref="authenticationFailureHandler"/>
    <logout success-handler-ref="logoutSuccessHandler"/>
    <anonymous/>
</http>
...
<global-method-security pre-post-annotations="enabled"> <!-- TODO: Add proxy-target-class="true" -->
    <expression-handler ref="expressionHandler"/>
</global-method-security>

<beans:bean id="expressionHandler"
          class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <beans:property name="permissionEvaluator" ref="cdmPermissionEvaluator"/>
</beans:bean>

<beans:bean id="loggerListener"
            class="org.springframework.security.authentication.event.LoggerListener"/>

<context:annotation-config/>

<beans:bean id="cdmPermissionEvaluator" class="org.gmeb.crf.server.auth.CdmPermissionEvaluator">
</beans:bean>

知道我在这里做错了吗?

在我进行此设置之前,我在@Service StudyServiceImpl中使用了@PostAuthorize注释和Spring EL表达式(没有permissionEvaluator),这很有用。那么我做错了什么,与之前的设置有什么不同?

提前致谢,

阿诺

1 个答案:

答案 0 :(得分:2)

这不起作用,因为您不能在单个方法上混合使用不同的注释类型而不会得到奇怪的结果。因此,建议您为要保护的每个类或接口选择一个“安全元数据”选项。

更详细地,可以在应用程序中使用多个不同的元数据源(安全注释,事后注释,切入点定义,JSR-250注释)。它们通常都由DelegatingMethodSecurityMetadataSource实例处理,它只会查询其代理,直到它从其中一个获得具体答案。因此,如果您为方法定义了@Secured@PreAuthorize,则只会使用一个。

您应该只在应用中定义了一个<global-method-security>元素。如果要将方法安全性应用于Web控制器或其中定义的其他bean,则只需将其放在-servlet.xml上下文文件中。