- 浏览: 240343 次
- 性别:
- 来自: 上海
最新评论
-
weigeshikebi:
不得不赞一个
解惑 spring 嵌套事务 -
siemens800:
Mac OS X 10.7.2 的光盘还有挖,帅锅帮刻个盘发来 ...
MacBook 升级内存记 -
cry615:
帖子很不错,java里任何一个东西都是一门学问,很有很强的逻辑 ...
理解 Java 的 GC 与 幽灵引用 -
sharkka:
sogo1986 写道楼主举的例 ...
解惑 spring 嵌套事务 -
sogo1986:
楼主举的例子并没用体 ...
解惑 spring 嵌套事务
本文原出处
http://starcraft.blogdriver.com/starcraft/1135045.html
在我之前的一篇文章里, 说明了在 Acegi 中如何将资源权限数据存储到数据库中, 文章见 http://www.hibernate.org.cn/viewtopic.php?t=17538,
虽然文中方式实现了从数据库读取资源权限, 但是代码量较大, 并且重载了 SecurityEnforcementFilter, 造成比较大的侵入性,
这里我将提供另一种更简洁的方式实现此功能.
入口还是 org.acegisecurity.intercept.web.FilterSecurityInterceptor, 资源权限配置来自于
objectDefinitionSource, 标准配置方式采用 FilterInvocationDefinitionSourceEditor 解析, 支持 Perl5 和 AntPath 两种风格,
为了实现从其它位置(典型如数据库), 我们要做的就是实现一个自定义的 FilterInvocationDefinitionSource, 查看类层次结构图后可以发现,
acegi 中已经有一个 AbstractFilterInvocationDefinitionSource 已经实现此接口, 只要实现一个抽象方法即可
因此, 自定义一个 Class 如下 :
因为 acegi 中已经提供了 Perl5 和 AntPath 的实现, 只需要集成过来即可, 因此定义接口如下
再让 RdbmsBasedFilterInvocationDefinitionSource 实现此接口即可, 下面是简略代码
ResourceMappingProvider
这样就很完美的既支持了从数据库的读取数据, 又可以自由选择 Perl5 和 AntPath 两种风格的配置, 最后不要忘了给 ResourceMappingProvider 加一层 cache, 我的配置如下
这段时间看了很多人对 Acegi 的评价, 有不少观点认为 Acegi 的配置太过繁琐, 其实权限控制本来就不是一件很轻松的事, Acegi 用 AOP 实现, 配置文件的确有些繁琐,
但是只要一个配置文件就解决了整个系统的权限问题, 可谓一劳永逸, 相比较在 Action 中实现应该还是利远大于弊, 也有人说用 WebWork 的 Interceptor 实现, 虽然也是不错的 solution,
但是不要忘了, 并不是所有的项目都使用 webwork , 假如有一个 struts 的项目, 权限控制就会有移植性的问题.
我的 msn : shartcn@msn.com, 有问题欢迎讨论
http://starcraft.blogdriver.com/starcraft/1135045.html
在我之前的一篇文章里, 说明了在 Acegi 中如何将资源权限数据存储到数据库中, 文章见 http://www.hibernate.org.cn/viewtopic.php?t=17538,
虽然文中方式实现了从数据库读取资源权限, 但是代码量较大, 并且重载了 SecurityEnforcementFilter, 造成比较大的侵入性,
这里我将提供另一种更简洁的方式实现此功能.
入口还是 org.acegisecurity.intercept.web.FilterSecurityInterceptor, 资源权限配置来自于
objectDefinitionSource, 标准配置方式采用 FilterInvocationDefinitionSourceEditor 解析, 支持 Perl5 和 AntPath 两种风格,
为了实现从其它位置(典型如数据库), 我们要做的就是实现一个自定义的 FilterInvocationDefinitionSource, 查看类层次结构图后可以发现,
acegi 中已经有一个 AbstractFilterInvocationDefinitionSource 已经实现此接口, 只要实现一个抽象方法即可
public abstract ConfigAttributeDefinition lookupAttributes(String url);
因此, 自定义一个 Class 如下 :
public class RdbmsBasedFilterInvocationDefinitionSource extends AbstractFilterInvocationDefinitionSource
因为 acegi 中已经提供了 Perl5 和 AntPath 的实现, 只需要集成过来即可, 因此定义接口如下
/** * <class>ConfigableFilterInvocationDefinition</class> 支持 Perl5 和 ant Path 两种风格的资源配置方式 * @since 2006-1-19 * @author 王政 * @version $Id: ConfigableFilterInvocationDefinition.java,v 1.3 2006/01/19 09:40:37 wz Exp $ */ public interface ConfigableFilterInvocationDefinition { /** The Perl5 expression */ String PERL5_KEY = "PATTERN_TYPE_PERL5"; /** The ant path expression */ String ANT_PATH_KEY = "PATTERN_TYPE_APACHE_ANT"; /** 标准分隔符 */ String STAND_DELIM_CHARACTER = ","; /** * Set resource expression, the value must be {@link #PERL5_KEY_REG_EXP} or {@link #ANT_PATH_KEY} * @see #REOURCE_EXPRESSION_PERL5_REG_EXP * @see #RESOURCE_EXPRESSION_ANT_PATH_KEY * @param resourceExpression the resource expression */ void setResourceExpression(String resourceExpression); /** * * @return resource expression */ String getResourceExpression(); /** * Set whether convert url to lowercase before comparison * @param convertUrlToLowercaseBeforeComparison whether convertUrlToLowercaseBeforeComparison */ void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison); /** * * @return whether convert url to lowercase before comparison */ boolean isConvertUrlToLowercaseBeforeComparison(); }
再让 RdbmsBasedFilterInvocationDefinitionSource 实现此接口即可, 下面是简略代码
/** * <class>RdbmsBasedFilterInvocationDefinitionSource</class> 是基于数据库的权限存储实现, 它支持两种风格的配置 * @see com.skyon.uum.security.acegi.intercept.web.ConfigableFilterInvocationDefinition * @see org.acegisecurity.intercept.web.RegExpBasedFilterInvocationDefinitionMap * @see org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap * @since 2006-1-19 * @author 王政 * @version $Id: RdbmsBasedFilterInvocationDefinitionSource.java,v 1.6 2006/02/13 03:20:55 wz Exp $ */ public class RdbmsBasedFilterInvocationDefinitionSource extends AbstractFilterInvocationDefinitionSource implements ConfigableFilterInvocationDefinition, InitializingBean { //~ Static fields/initializers ============================================= private static final Log logger = LogFactory.getLog(RdbmsBasedFilterInvocationDefinitionSource.class); // ~ Instance fields ======================================================== private String resourceExpression = PERL5_KEY; private boolean convertUrlToLowercaseBeforeComparison = false; private ResourceMappingProvider resourceMappingProvider; // ~ Methods ================================================================ /** * * @see org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource#lookupAttributes(java.lang.String) */ public ConfigAttributeDefinition lookupAttributes(String url) { FilterInvocationDefinitionSource actualSource = populateFilterInvocationDefinitionSource(); if (RegExpBasedFilterInvocationDefinitionMap.class.isInstance(actualSource)) { return ((RegExpBasedFilterInvocationDefinitionMap) actualSource).lookupAttributes(url); } else if (PathBasedFilterInvocationDefinitionMap.class.isInstance(actualSource)) { return ((PathBasedFilterInvocationDefinitionMap) actualSource).lookupAttributes(url); } throw new IllegalStateException("wrong type of " + actualSource + ", it should be " + RegExpBasedFilterInvocationDefinitionMap.class + " or " + PathBasedFilterInvocationDefinitionMap.class); } /** * * @see org.acegisecurity.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions() */ public Iterator getConfigAttributeDefinitions() { FilterInvocationDefinitionSource actualSource = populateFilterInvocationDefinitionSource(); if (RegExpBasedFilterInvocationDefinitionMap.class.isInstance(actualSource)) { return ((RegExpBasedFilterInvocationDefinitionMap) actualSource).getConfigAttributeDefinitions(); } else if (PathBasedFilterInvocationDefinitionMap.class.isInstance(actualSource)) { return ((PathBasedFilterInvocationDefinitionMap) actualSource).getConfigAttributeDefinitions(); } throw new IllegalStateException("wrong type of " + actualSource + ", it should be " + RegExpBasedFilterInvocationDefinitionMap.class + " or " + PathBasedFilterInvocationDefinitionMap.class); } private FilterInvocationDefinitionSource populateFilterInvocationDefinitionSource() { FilterInvocationDefinitionMap definitionSource = null; if (PERL5_KEY.equals(getResourceExpression())) { definitionSource = new RegExpBasedFilterInvocationDefinitionMap(); } else if (ANT_PATH_KEY.equals(getResourceExpression())) { definitionSource = new PathBasedFilterInvocationDefinitionMap(); } else { throw new IllegalArgumentException("wrong resourceExpression value"); } definitionSource.setConvertUrlToLowercaseBeforeComparison(isConvertUrlToLowercaseBeforeComparison()); ResourceMapping[] mappings = getResourceMappingProvider().getResourceMappings(); if (mappings == null || mappings.length ==0) { return (FilterInvocationDefinitionSource) definitionSource; } for (int i = 0; i < mappings.length; i++) { ResourceMapping mapping = mappings[i]; String[] recipents = mapping.getRecipients(); if (recipents == null || recipents.length == 0) { if (logger.isErrorEnabled()) { logger.error("Notice, the resource : " + mapping.getResourcePath() + " hasn't no recipents, it will access by any one ! "); } continue; } StringBuffer valueBuffer = new StringBuffer(); for (int j = 0; j < recipents.length; j++) { valueBuffer.append(recipents[j]); if (j < recipents.length - 1) { valueBuffer.append(STAND_DELIM_CHARACTER); } } String value = valueBuffer.toString(); addSecureUrl(definitionSource, mapping.getResourcePath(), value); } return (FilterInvocationDefinitionSource )definitionSource; } /** * @param source * @param name * @param value * @throws IllegalArgumentException */ private synchronized void addSecureUrl(FilterInvocationDefinitionMap source, String name, String value) throws IllegalArgumentException { // Convert value to series of security configuration attributes ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor(); configAttribEd.setAsText(value); ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd.getValue(); // Register the regular expression and its attribute source.addSecureUrl(name, attr); } 省去 getter, setter.... }
ResourceMappingProvider
public interface ResourceMappingProvider { String RESOURCE_PATH_PREFIX = "/"; /** * Get Resource Mapping * @return resource mapping */ ResourceMapping[] getResourceMappings(); } public class ResourceMapping { // url private String resourcePath; // 即角色 private String[] recipients = new String[0]; 省去 getter, setter.... }
这样就很完美的既支持了从数据库的读取数据, 又可以自由选择 Perl5 和 AntPath 两种风格的配置, 最后不要忘了给 ResourceMappingProvider 加一层 cache, 我的配置如下
<bean id="resourceCache" class="com.skyon.uum.security.acegi.intercept.web.cache.EhCacheBasedResourceCache"> <property name="dataSource"> <ref bean="dataSource"></ref> </property> <property name="cache"> <bean parent="cacheTemplate"> <property name="cacheName"><value>resourceCache</value></property> </bean> </property> <property name="allResourcesQuery"> <value> select distinct t.id, t.id, t.parent_id, t.url, t.title, t.layer, t.type, t.application_id from uum_resource t order by t.orderField </value> </property> </bean> <bean id="permissionCache" class="com.skyon.uum.security.acegi.intercept.web.cache.EhCacheBasedPermissionCache"> <property name="dataSource"> <ref bean="dataSource"></ref> </property> <property name="cache"> <bean parent="cacheTemplate"> <property name="cacheName"><value>permissionCache</value></property> </bean> </property> <property name="recipentsResourceMappingQuery"> <value> select r.name, p.resource_id from uum_permission p left outer join uum_role r on p.role_id = r.id </value> </property> </bean> <bean id="resourceMappingProvider" class="com.skyon.uum.security.acegi.intercept.web.ResourceMappingProviderImpl" autowire="byType"/> <!-- ======================== AUTHENTICATION ======================= --> <!-- Note the order that entries are placed against the objectDefinitionSource is critical. The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL. Accordingly, you should place MOST SPECIFIC (ie a/b/c/d.*) expressions first, with LEAST SPECIFIC (ie a/.*) expressions last --> <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager"><ref local="authenticationManager"/></property> <property name="accessDecisionManager"><ref local="accessDecisionManager"/></property> <property name="objectDefinitionSource"><ref local="filterInvocationDefinitionSource"></ref></property> </bean> <bean id="filterInvocationDefinitionSource" class="com.skyon.uum.security.acegi.intercept.web.RdbmsBasedFilterInvocationDefinitionSource"> <property name="resourceMappingProvider"> <ref local="resourceMappingProvider"></ref> </property> <property name="resourceExpression"> <value>PATTERN_TYPE_APACHE_ANT</value> </property> </bean>
这段时间看了很多人对 Acegi 的评价, 有不少观点认为 Acegi 的配置太过繁琐, 其实权限控制本来就不是一件很轻松的事, Acegi 用 AOP 实现, 配置文件的确有些繁琐,
但是只要一个配置文件就解决了整个系统的权限问题, 可谓一劳永逸, 相比较在 Action 中实现应该还是利远大于弊, 也有人说用 WebWork 的 Interceptor 实现, 虽然也是不错的 solution,
但是不要忘了, 并不是所有的项目都使用 webwork , 假如有一个 struts 的项目, 权限控制就会有移植性的问题.
我的 msn : shartcn@msn.com, 有问题欢迎讨论
评论
5 楼
1123321
2007-07-27
大哥,能否借您的完整代码Look一下,我从您原来的blog:
http://starcraft.blogdriver.com/starcraft/找到这里,实在没有找到您的联系方式,所以留下自己的联系方式:
QQ:56868655
MSN:cn_zhongyiming@hotmail.com
静侯佳音!
祝您工作愉快!
http://starcraft.blogdriver.com/starcraft/找到这里,实在没有找到您的联系方式,所以留下自己的联系方式:
QQ:56868655
MSN:cn_zhongyiming@hotmail.com
静侯佳音!
祝您工作愉快!
4 楼
malinser
2007-01-21
你好,我正在做ACegi的论文,有些问题想请教一下,我QQ是14453787,希望你的指导
3 楼
acerjsj
2006-12-26
2 楼
kjj
2006-07-31
楼主使用了cache 数据库资源的方法动态更新配置资源
没有提供cache类 的代码啊 那几个查询语句 不甚明白阿
没有提供cache类 的代码啊 那几个查询语句 不甚明白阿
1 楼
baizheng
2006-02-22
嗯,我是支持Acegi 的
发表评论
-
Bookmarks
2010-07-07 16:42 1529Architecture J2EE cluster htt ... -
XML validation error on request: cvc-complex-type
2010-04-15 21:45 1380see http://72.5.124.102/threa ... -
Spring LoadTimeWeaver 的那些事儿
2009-10-05 00:39 4095DDD 现在越来越流行了, 不管正确与否, new U ... -
理解 Java 的 GC 与 幽灵引用
2009-06-04 03:02 3295理解 Java 的 GC 与 幽灵引用 J ... -
基于 Apache Mina 的 RPC 实现 (长连接 webservice)
2008-11-27 23:26 4393写了一个基于 Apache Mina 和 SpringRemo ... -
Atomikos JTA for Hibernate3
2007-11-22 14:52 3369http://wiki.atomikos.org/bin/vi ... -
Spring AOP 概览与细节
2007-08-05 03:21 6047@王政 @2007-08-04 @转载请注明 ... -
解惑 spring 嵌套事务
2006-11-25 01:03 36225解惑 spring 嵌套事务 /** * @au ... -
使用 FactoryBean 让你的 spring 配置动起来
2006-11-01 17:43 10496看到不少朋友讨论 spring 配置时认为 spring 配置 ... -
一个可能的列级权限控制方案讨论
2006-05-25 18:45 18024最近的项目需要做到列级权限控制, 大意如下 publi ... -
Spring 事务简化配置
2006-03-21 00:33 36805在 spring 中, 事务管理一般是通过声明一个 txPr ... -
以前写的一篇介绍 Acegi 的文档
2006-01-05 09:51 13304半年前写的, 版本是 0.8.3, 主要是翻译了一些 ref ... -
Acegi 资源配置动态扩展实现
2005-12-13 16:21 19202本文原出处 : http://starcr ...
相关推荐
Spring Acegi权限控制是Spring框架中用于实现Web应用安全的一种解决方案。Acegi Security(现已被Spring Security替代)是一个功能强大的安全框架,它主要解决了认证(Authentication)和授权(Authorization)这两...
总的来说,这个"最简单acegi权限管理实例"是一个很好的学习起点,通过实践可以了解Acegi的基本用法,包括用户认证、权限控制、配置文件的理解以及如何与Spring框架集成。在实际项目中,我们需要根据需求进行更复杂的...
- "db"可能指的是数据库相关的配置或日志,Acegi通常需要配置用户数据库来存储用户信息和权限数据。 - "aopacegi"可能是一个包含Acegi与AOP相关配置或实现的文件,可能涉及切面的定义和安全策略的配置。 Acegi ...
在本实例中,我们将深入探讨如何使用Acegi来控制用户的权限。Acegi Security已经被Spring Security替代,但其核心思想和机制仍然适用于现代的Spring Security。 首先,我们需要理解Acegi的基础概念。Acegi的核心是`...
2. **数据库配置**:Acegi允许将安全配置存储在数据库中,这意味着安全策略可以动态地进行修改,而无需每次变动时都重新部署应用。这在权限复杂多变的企业级应用中非常实用,管理员可以直接在数据库层面进行权限的增...
开发者还可以通过实现自定义的UserDetailsService接口来获取和验证用户信息,这使得AceGI能够与现有的用户存储系统(如数据库或LDAP)集成。 另外,AceGI提供了丰富的日志和审计功能,可以帮助开发者追踪和分析安全...
Acegi Java权限验证框架是Spring Security的前身,它是一个强大且灵活的安全框架,用于Java企业级应用程序。这个框架提供了一套完整的解决方案,包括用户认证、访问控制、安全配置以及会话管理等多个方面,旨在帮助...
Acegi的强大之处在于它能够无缝集成到Spring环境中,使得开发者可以方便地实现复杂的权限控制策略。在本项目中,Acegi主要负责用户的登录验证、角色分配以及资源访问权限的控制。 Appfuse是一个开源项目,旨在简化...
在Spring和Acegi的结合中,Acegi提供了一个灵活且可扩展的安全基础设施,而LDAP作为身份验证和授权的数据源,可以存储用户账户信息和权限设置。将Acegi与LDAP整合,可以使应用程序利用LDAP服务器进行用户登录验证和...
标题 "batis+acegi实现的动态权限控制" 暗示了这个项目是关于整合Spring框架中的Acegi安全模块和MyBatis ORM框架,来创建一个动态的权限管理系统。Acegi是Spring早期的安全组件,现在已被Spring Security所取代,但...
不同于传统的安全框架,Acegi采用了面向切面编程(AOP)的方式来处理认证和授权问题,这使得它能够与业务代码保持高度的解耦,同时也赋予了开发人员更多的灵活性来定制安全策略。本文将深入探讨Acegi的关键组件、...
在权限管理中,我们可能需要存储用户、角色和权限的相关信息。通过Hibernate,我们可以方便地创建这些实体类,定义它们之间的关系,并实现CRUD操作。 4. **配置Acegi与Hibernate** 配置Acegi以使用Hibernate进行...
此外,Acegi Security还支持预授权和后授权策略,使得权限管理更加灵活。 三、会话管理 Acegi Security对会话进行了强化管理,可以防止会话劫持、会话固定攻击等。它提供了会话超时检测、会话固定保护(session-...
在 `acegi-config.xml` 文件中,你可以定义认证和授权策略,比如用户存储(UserDetailsService)、认证管理器(AuthenticationManager)和权限访问决策器(AccessDecisionManager)。 Acegi 还提供了许多预定义的...
Acegi框架的核心是它对用户认证和权限控制的处理。它允许开发者定义复杂的认证机制,如基于用户名和密码的登录,或者支持数字证书等。同时,Acegi提供了细粒度的授权机制,可以基于角色、URL、方法级别进行访问控制...
Acegi_db1.rar_acegi 是一个与Acegi安全框架相关的压缩包,它可能包含了用于数据库配置和安全策略实现的源代码以及相关的说明文档。Acegi是Spring Security的前身,是一个非常重要的Java安全框架,主要用于企业级...
由于Acegi默认配置文件策略可能无法满足所有场景下的需求,尤其是在需要动态调整用户权限的情况下。为了解决这一问题,可以采用基于数据库的策略来进行动态扩展。 - **基于数据库的策略**: 1. 将权限信息存储在...
2. `application.properties`:这个文件用于存储应用的属性,可以包含Grails Acegi插件的配置参数,如用户的认证方式、权限设置等。 3. `plugin.xml`:XML格式的插件配置文件,通常包含插件的版本、作者等信息,有时...
这个版本的jar文件"acegi-security-tiger-1.0.7.jar"是该框架的核心库,包含了实现安全控制的所有类和接口,使得开发者能够更方便地管理用户的登录、权限分配以及访问控制。 Acegi Security的主要功能包括: 1. **...