论坛首页 Java企业应用论坛

请问这样的细粒度权限能否用acegi实现?

浏览 48280 次
该帖已经被评为精华帖
作者 正文
   发表时间:2006-01-05  
robbin 写道

我认为合理的控制方式是在Web Action来进行拦截(本质上等于基于URL的控制),


对URL的拦截也是acegi的强项。

如果robbin指的真的是对url的拦截,我可以讲讲acegi如何对url拦截,其实就是一个filter
0 请登录后投票
   发表时间:2006-01-05  
Feiing 写道

我认为大多数人对 Acegi 都有些偏见,  如果稍微花点时间了解,  相信会改变看法,  正如上面某位仁兄所述, Acegi 的复杂度在于对多种环境的支持,  大多数应用也只是用到其中某些功能, 要做的只不过是把 example 的配置文件拷过来稍做修改 

其实说了半天, 俺的观点就是 : acegi 是一个高度可扩展, 可复用的 security framework


Feiing你好,早就听说过您的大名,小弟正是那个“某位仁兄”,望有机会一起探讨。
0 请登录后投票
   发表时间:2006-01-05  
差沙 写道
robbin 写道

我认为合理的控制方式是在Web Action来进行拦截(本质上等于基于URL的控制),


对URL的拦截也是acegi的强项。

如果robbin指的真的是对url的拦截,我可以讲讲acegi如何对url拦截,其实就是一个filter


好阿,期待你的示例。
0 请登录后投票
   发表时间:2006-01-05  
就robbin的web层给一个具体的例子,争取写的完善点。

首先要配置一个filter,这个filter用一个代理bean写在了spring里面,其实根正常的filter没有任何区别。
	<bean id="securityEnforcementFilter"
		class="org.acegisecurity.intercept.web.SecurityEnforcementFilter">
		<property name="filterSecurityInterceptor">
			<ref local="filterInvocationInterceptor" />
		</property>
		<property name="authenticationEntryPoint">
			<ref local="authenticationProcessingFilterEntryPoint" />
		</property>
	</bean>


"filterInvocationInterceptor" 是一个拦截器,说是拦截器,其实就是在filter里面执行一下他的拦截方法,这里可没有什么aop.
authenticationEntryPoint 交验失败的时候转到的地方,为什么说是地方,因为通过配置可以转到其它的url甚至其它的协议下(http 转到 https等等)
0 请登录后投票
   发表时间:2006-01-05  
	<bean id="authenticationProcessingFilterEntryPoint"
		class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
		<property name="loginFormUrl">
			<value>/error.security</value>
		</property>
		<property name="forceHttps">
			<value>false</value>
		</property>
	</bean>


这个就是失败的时候转到的地方,我们可以配置url和是否使用https

	<bean id="filterInvocationInterceptor"
		class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
		<property name="authenticationManager">
			<ref bean="authenticationManager" />
		</property>
		<property name="accessDecisionManager">
			<ref local="httpRequestAccessDecisionManager" />
		</property>
		<property name="objectDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/index.jsp=ROLE_ANONYMOUS,ROLE_USER
				/j_acegi_switch_user=ROLE_SUPERVISOR
				/login.security=ROLE_ANONYMOUS,ROLE_USER				/test.do=ROLE_CODER
				/**.do*=ROLE_USER
			</value>
		</property>
	</bean>


这个就是前面提到的拦截器。简单解释一下:
authenticationManager 在acegi里面的主要作用就是管理维护用户的权限角色等信息,比方说想要用户的ROLE就要在这里面拿了。里面配置了多种全县的来源,可以从DAO里面来(就是数据库里面),可以是cookies里面的,也可以是匿名的权限,每种权限都以一种Provider的形式提供:
	<bean id="authenticationManager"
		class="org.acegisecurity.providers.ProviderManager">
		<property name="providers">
			<list>
				<ref local="daoAuthenticationProvider" />
				<ref local="anonymousAuthenticationProvider" />
				<ref local="rememberMeAuthenticationProvider" />
			</list>
		</property>
	</bean>


objectDefinitionSource在acegi里面就是配置权限信息,说明哪一个url需要什么权限才能访问,acegi默认用<value>来表示,其实这正是acegi的不足之处,还好能够补救。我来说明一下:
我们知道在spring里面<value>标签比较特殊,spring首先找到这个属性的类型,然后把value里面的内容以String的类型取出来(Spring做了一下包装,为TypedString)。然后根据这个属性的类型找他的Editer,然后用Editer来处理String为需要的类型。但是我们不希望用String来表达url,很明显url里面有=就不会玩了。我们可以把这个信息写到数据库里面,然后读取,这里面不说了以前有一位高手已经解释过了。

接下来就是httpRequestAccessDecisionManager了,AccessDecisionManager在acegi里面是决策者,就是根据你所拥有的权限和访问URL需要的权限来决定你到底能不能访问。

	<bean id="httpRequestAccessDecisionManager"
		class="org.acegisecurity.vote.AffirmativeBased">
		<property name="allowIfAllAbstainDecisions">
			<value>false</value>
		</property>
		<property name="decisionVoters">
			<list>
				<ref bean="roleVoter" />
			</list>
		</property>
	</bean>


决策者里面是投票者,这个上面已经解释过了,一个投票者校验一种权限。整个流程已经说完了。
0 请登录后投票
   发表时间:2006-01-05  
流程说完了,接下对上面提到的问题解释一下:
引用

先使用URL拦截的方式去对付大多数的情况,然后少数URL搞不定的再加一个接口,让Action自己去判别。这样用两个拦截器对Action进行拦截,如果Action实现了hasPermission接口,那么就交给Action自己判断,如果Action没有该接口,就查找内部的URL和权限的对照表来判断。


这个情况比较复杂,因为是要对Action进行调用,所以要看使用的web框架来定夺。是用不同Web框架要是用不同的Web框架拦截器。所以恐怕acegi力不从心,挺多在filter里面配置一下是否要是用Action自身校验。但是想法很好,赞。

引用

你怎么把信息有效的传递给Web层和其他的Facade层进行用户友好性的提示处理?


acegi校验失败的时候会抛出AuthenticationException异常,然后放在session里面,
在错误转向页面可以这样是用
<%= ((AuthenticationException); session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY););.getMessage(); %>
<%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY); %>
<%= session.getAttribute(SecurityEnforcementFilter.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY); %>

不过这么用实在太难看了,晕了。可以自己用tag来搞定

引用

很多系统需要根据权限不同,生成不同的UI组件(例如管理员的菜单和普通用户菜单就肯定不一样),这也需要在Web层的View进行控制。

acegi对View的处理就是使用tag,原来的acegi好像没有什么tag,简直是烂,现在有了tag,说一下是用的方法,但是说实话他的tag实在是不够强。

老版的web.xml
<taglib>
  <taglib-uri>http://acegisecurity.sf.net/authz</taglib-uri>
  <taglib-location>/WEB-INF/authz.tld</taglib-location>
</taglib>

在页面中使用
<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
<td>
<A HREF="del.htm?id=<c:out value="${contact.id}"/>">Del</A>
</td>
</authz:authorize>

ifAllGranted是说所有的权限都有,用','分割权限
可以替换成ifAnyGranted:  ifNotGranted:

<authz:authentication operation="username"/>


这个是用来显示你的权限信息的。

<authz:acl domainObject="${contact}" hasPermission="16,1">
<td><A HREF="<c:url value="del.htm"><c:param name="contactId"
value="${contact.id}"/></c:url>">Del</A></td>
</authz:acl>


这个是ACL的,acegi里面新推出的ACL模型实在是一大亮点,找时间写一个专门介绍acegi的ACL模型的帖子。
0 请登录后投票
   发表时间:2006-01-05  
谢谢你的例子,不过我还看不太懂,有很多问题不解,等有空学习一把Acegi再来讨教。

引用
这个情况比较复杂,因为是要对Action进行调用,所以要看使用的web框架来定夺。是用不同Web框架要是用不同的Web框架拦截器。所以恐怕acegi力不从心,挺多在filter里面配置一下是否要是用Action自身校验。但是想法很好,赞。


使用Webwork的话写Action拦截器和配置拦截器都超简单,不赘述了。
使用Struts/Spring的话,可以使用Spring的拦截器。不过这里面我有一个很大的疑问:就是Spring的拦截器怎么去拿到HttpSession里面的用户信息,从而拿到role进行权限判别?Webwork的拦截器通过ThreadLocal方式的ActionContext提供了不依赖Servlet容器的相关信息,但是Spring没有提供相关设施,兴许Spring有某个提供了ServletContext的回调接口(我不熟悉spring MVC所以只是猜测),只要拦截器实现该接口就可以得到ServletContext,从而拿到HttpSession。然而这样的方式也和Servlet API偶合了,无法脱离容器进行单元测试(必须用Mock),还是不如Webwork方便。

引申一步,对于现在AJAX方式的分布式调用,都是跳过Web层直接访问业务bean的,这时候都需要获得HttpSession,进行身份识别,我不知道大家是怎么做的。


引用
acegi校验失败的时候会抛出AuthenticationException异常,然后放在session里面,
在错误转向页面可以这样是用


这种方式有点太粗了,即使权限不通过,也可能有n种不同情况需要分别处理,你必须自己定义一个异常继承的体系结构去应对不同的情况。这个时候,Acegi是否支持方便的抛出我们自定义的各种异常?这种情况对于web层处理起来更方便,特别是webwork。

Acegi可能是太通用了,从上面讨论我总感觉如果自己去写权限管理很简单的事情,如果用Acegi,会麻烦好多,特别是那么多配置和常量定义,让我望而生畏,而且特定项目的需求肯定不可避免对Acegi进行定制和扩展。

Acegi似乎是Spring对应于J2EE的JAAS实现,Spring Acegi vs J2EE JAAS, 但是Acegi比JAAS更强大,更灵活,可移植性更好,更适合对付系统资源方面的权限控制,而不是业务逻辑方面的权限控制。
0 请登录后投票
   发表时间:2006-01-05  
引用
使用Struts/Spring的话,可以使用Spring的拦截器。不过这里面我有一个很大的疑问:就是Spring的拦截器怎么去拿到 HttpSession里面的用户信息,从而拿到role进行权限判别?Webwork的拦截器通过ThreadLocal方式的 ActionContext提供了不依赖Servlet容器的相关信息,但是Spring没有提供相关设施,兴许Spring有某个提供了 ServletContext的回调接口(我不熟悉spring MVC所以只是猜测),只要拦截器实现该接口就可以得到ServletContext,从而拿到HttpSession。然而这样的方式也和 Servlet API偶合了,无法脱离容器进行单元测试(必须用Mock),还是不如Webwork方便。

引申一步,对于现在AJAX方式的分布式调用,都是跳过Web层直接访问业务bean的,这时候都需要获得HttpSession,进行身份识别,我不知道大家是怎么做的。


自问自答一把。可以自己写一个ServletFilter,把Webwork那些对应ActionContext相关的代码拷贝过来,在ServletFilter里面初始化和组装,随后就可以在Spring拦截器里面用Webwork那种方式使用request,session,context了。不过还是不知道大家是怎么处理的?
0 请登录后投票
   发表时间:2006-01-05  
引用
下载了你的开源框架,没找到你在哪里用AOP加入role的代码。权限确实适合用AOP去解决。

bba96-security是我另一个开源项目,可能也会加到bba96里面去。其实也很简单,只是用到bba96的query接口,然后自己定义一套security的接口给具体项目的role, user, group, resource, permission,只有一个securityManager跟permissionInterceptor是实现类,可以很方便的实现数据权限,以及权限的允许,限制,包含,还可以通过多种方式(自身冗余字段/连接表字段/子查询)让user对resource在group关系上的权限继承,所需要做的只是让resource实现不同的接口,对resource在department/type等其他关系的,就只能同过数据权限,就不能继承了(当然实现起来也可以,但是复杂度更高),这样用AOP控制下来,你就发现在权限控制方面是很自由的了。只用维护一个permission表,就可以随意对resource进行细到每个字段,甚至是他的关联字段的控制。


acegi是很好,通用性也拌住了自己的脚,ACL也不是多么好的模型,用起来不会有让你有自由的感觉,不值得花太多功夫下去。不知道acegi有没有query接口,可以让用户实现,而它对于这个query接口来进行AOP的权限控制,我觉得这才是根本之道。
0 请登录后投票
   发表时间:2006-01-05  
lllyq 写道
引用
下载了你的开源框架,没找到你在哪里用AOP加入role的代码。权限确实适合用AOP去解决。

bba96-security是我另一个开源项目,可能也会加到bba96里面去。其实也很简单,只是用到bba96的query接口,然后自己定义一套security的接口给具体项目的role, user, group, resource, permission,只有一个securityManager跟permissionInterceptor是实现类,可以很方便的实现数据权限,以及权限的允许,限制,包含,还可以通过多种方式(自身冗余字段/连接表字段/子查询)让user对resource在group关系上的权限继承,所需要做的只是让resource实现不同的接口,对resource在department/type等其他关系的,就只能同过数据权限,就不能继承了(当然实现起来也可以,但是复杂度更高),这样用AOP控制下来,你就发现在权限控制方面是很自由的了。只用维护一个permission表,就可以随意对resource进行细到每个字段,甚至是他的关联字段的控制。


acegi是很好,通用性也拌住了自己的脚,ACL也不是多么好的模型,用起来不会有让你有自由的感觉,不值得花太多功夫下去。不知道acegi有没有query接口,可以让用户实现,而它对于这个query接口来进行AOP的权限控制,我觉得这才是根本之道。


那就等着看你完整的框架代码了。bba96简单浏览了一遍,感觉还是很不错的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics