我是有关 Spring 和 Spring 安全框架的新手,并尝试使用 Spring Security v3.1.4 保护在最新稳定 Glassfish 构建上运行的 Java EE 7 REST 应用程序。
一切都很好,但我无法让“全局方法安全”工作!这是我的配置,任何帮助将不胜感激。
网页.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Spring 应用程序上下文配置为预身份验证,如下所示:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true" />
</bean>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map request-matcher="ant">
<sec:filter-chain pattern="/api/authentication" filters="none"/>
<sec:filter-chain pattern="/**" filters="sif,requestHeaderAuthFilder,logoutFilter,etf,fsi"/>
</sec:filter-chain-map>
</bean>
<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref='preAuthenticatedAuthenticationProvider'/>
</sec:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="preAuthenticatedUserDetailsService"/>
</bean>
</property>
</bean>
<bean id="preAuthenticatedUserDetailsService"
class="org.someUserDetailsService"/>
<bean id="requestHeaderAuthFilder" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="principalRequestHeader" value="sometoken"/>
</bean>
<bean id="preAuthenticatedProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
<bean id="etf" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="preAuthenticatedProcessingFilterEntryPoint"/>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
<ref bean="authenticatedVoter"/>
</list>
</property>
</bean>
<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadataSource">
<sec:filter-security-metadata-source use-expressions="true">
<!--<sec:intercept-url pattern="/api/authentication" access="permitAll"/>-->
<sec:intercept-url pattern="/**" access="isAuthenticated()"/>
</sec:filter-security-metadata-source>
</property>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<bean id="authenticatedVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
以下是 Spring ACL 配置:
<sec:global-method-security
pre-post-annotations="enabled">
<sec:expression-handler ref="expressionHandler" />
</sec:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="aclPermissionEvaluator" />
</bean>
<bean name="aclPermissionEvaluator"
class="org.CustomPermissionEvaluator">
<constructor-arg name="aclService" ref="aclService" />
<property name="sidRetrievalStrategy" ref="someSidRetrievalStrategy" />
</bean>
<bean id="lookupStrategy"
class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg name="dataSource" ref="dataSource" />
<constructor-arg name="aclCache" ref="aclCache" />
<constructor-arg name="aclAuthorizationStrategy" ref="aclAuthorizationStrategy" />
<constructor-arg name="auditLogger" ref="auditLogger" />
</bean>
<bean id="aclCache"
class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
</property>
<property name="cacheName" value="aclCache" />
</bean>
</constructor-arg>
</bean>
<bean id="aclAuthorizationStrategy"
class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg name="auths">
<list>
<!-- authority for taking ownership -->
<bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_ADMIN" />
</bean>
<!-- authority to modify auditing -->
<bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_ADMIN" />
</bean>
<!-- authority to make general changes -->
<bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_ADMIN" />
</bean>
</list>
</constructor-arg>
<property name="sidRetrievalStrategy" ref="someSidRetrievalStrategy"/>
</bean>
<bean id="someSidRetrievalStrategy" class="org.SomeSidRetrievalStrategyImpl"/>
<bean id="auditLogger"
class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
<jee:jndi-lookup
id="dataSource"
jndi-name="springacl" />
<bean id="aclService" name="aclService"
class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg name="dataSource" ref="dataSource" />
<constructor-arg name="lookupStrategy" ref="lookupStrategy" />
<constructor-arg name="aclCache" ref="aclCache" />
<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))" />
<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))" />
</bean>
我要应用权限检查的方法如下所示:
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasPermission(#id, 'read')")
public Project getProject(@PathParam("id") Long id) {
}
我在哪里做错了?