如何配置Spring Security的global-method-security属性


最近的这个项目是Flex + Spring + Hibernate + Spring Security的技术框架。

由于Flex需要和SpringIOC管理的Service对象进行数据交换,所以用到了Flex称为AMF的技术,实际上就是远程调用。

通常来说,Web类型的项目使用Spring Security做到基于URL的安全控制也就行了。但是现在这个项目因为AMF的缘故,暴露了Service对象,对于这部分内容也需要使用Spring Security做统一的访问控制。

技术上,SpringSecurity能够提供了方法级别的安全控制,不过在配置的时候还是碰到了不少的问题,在此记录下来,供自己以后查阅,也希望能够帮到需要帮助的同仁。

Spring Security提供了两种方法实现方法级安全控制。
第一种,在方法上添加注解,这种方法除了能够控制此方法允许访问的角色, 还能够与ACL一起提供基于数据级的访问控制。但是此种方法会令权限控制代码分散在Java代码中,为今后的维护和变更带来了风险。
第二种,利用aspectj框架,在配置文件中编写方法访问控制规则,基于面向切面编程的思想,访问控制代码完全和业务代码分离,开发人员无需关心权限控制的问题,但是需要在开发之前定义好业务代码方法命名规则。此种方法虽然能够比较完美的把权限控制代码和业务代码分离,但是不能结合ACL做数据级权限控制。

因为目前的项目业务简单,并且还未使用ACL机制,所以准备以aspectj为主,辅以注解的形式控制方法安全。

首先<http>部分的配置和普通的Web项目配置没有什么两样,不再做介绍,最重要的是<global-method-security>的位置。下面是我配置以及发现问题的过程:

按照官方的sample首先解决了aspectj的依赖问题,测试发现<http>部分基于URL过滤的控制已经生效,但是在远程调用这块的控制始终不能成功,并且项目在启动的时候也没有任何异常信息。

反复和spring security提供的sample做比较,发现自己的配置没有什么异样,但是方法过滤始终未能生效,在Google上反复查找,偶然发现一位同仁遇到了相同的问题,而且还是自问自答 O(∩_∩)O
Global Method Security,原文中提到:

Configuration which solved the problem:I had to move the <global-method-security> definition to the first file (spring-ws-servlet.xml) & before the CustomerController bean is initialized.

意思就是在Bean实例化之前配置<global-method-security>属性。为什么需要这样子,Spring官方论坛也没有回答,按道理来说,global-method-security放置在什么位置应该不会有差异才对的。或许这是一个BUG。

按照Global Method Security的说法,我把<global-method-security>移到了flex-servlet.xml文件中,并且放置在<context:component-scan>之前,再次启动服务器测试,大功告成!方法过滤终于生效了。

项目的相关配置
web.xml

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!– 省略若干配置 –>

<servlet>
<servlet-name>flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

flex-servlet.xml (根据web.xml配置文件中的servlet-name自动查找WEB-INF目录下的flex-servlet.xml文件)

<flex:message-broker>
<flex:remoting-service default-channels=”my-amf”/>
</flex:message-broker>

<security:global-method-security pre-post-annotations=”enabled”>
<security:protect-pointcut expression=”execution(* com.leo.service.**.*.save*(..))” access=”hasRole(‘ROLE_ADMIN’)”/>
</security:global-method-security>

<context:component-scan base-package=”com.leo.service” />

flex/services-config.xml(由于flex-servlet.xml中配置了<flex:message-broker>,所以工程在启动的时候会自动查找/WEB-INF/flex目录下的services-config.xml文件)

<channels>
<channel-definition id=”my-amf” class=”mx.message.channels.AMFChannel”>
<endpoint url=”http://{server.name}:{server.port}/{context.root}/messagebroker/amf” class=”flex.message.endpoints.AMFEndpoint”/>
</channel-definition>
</channels>

spring/security-config.xml

<http auto-config=”true”>
<intercept-url pattern=”/**” access=”hasRole(‘ROLE_USERS’)”/>
</http>

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s