posts - 193,  comments - 520,  trackbacks - 0
 
今天对acegi的页面标签做扩展,突然发现找不到tld文件了
Jsp中非常简单:
<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
但记得自己没有在web.xml中声明这个标签,咋就跑起来了呢?google一下,原来authz.tld被打入jar包的META-INF下
呵呵,记录一下
posted @ 2006-10-12 15:50 ronghao 阅读(614) | 评论 (0)编辑 收藏
acegi内置了对CAS的支持。这里的CAS是3.0。建立CAS server是一个比较简单的事情。CAS server就是一个标准的war文件,把它发布就可以运行。需要做的仅仅是调整登陆和其他一些页面。先了解一下CAS如何实现SSO。
例子:原有系统A和系统B,现在在它们之间做SSO。
很显然,系统A和B都是CAS client。首先是访问系统A,干掉A的登陆页面,在A的入口判断有没有Ticket(票据),如果没有则重定向到CAS server,在CAS server提供Credential(大多数情况就是用户名和密码)。CAS server的作用非常简单:就是来验证用户密码。正确,则发送Ticket。CAS有5种Ticket,分别是TGC(通过cookie发送的ticket),ST(Service Ticket),PGT,PGTIOU,PT。其中PGT,PGTIOU,PT属于代理ticket,这里不作讨论。具体可以参考
http://www.blogjava.net/openssl/archive/2006/04/26/SSO_CASProxy.html
TGC和ST的关系可以打个比方:
我去中央电视塔去玩,结果发现地下还有个海底世界。SSO前我是这么玩的:先去电视塔买张门票,玩完了;再去海底世界买张门票,玩完了。发现真累,两个景点这么近还要买两次门票,就不能搞个通票吗?于是就SSO。于是这样:我先去电视塔,门卫告诉我你不能进去要买票,于是把我送到通票售票处(CAS server)买票(登录),买吧,于是给了我两张票,注意,是两张,一张发到我手里,上面写着仅限电视塔使用(ST);靠,不是通票吗,咋仅限电视塔使用?别急,还有一张票(TGC)通过cookie发送你看不见。人家说了保证没问题,我咋办,这是人家的规矩,那就先去玩吧。出了电视塔我直扑海底世界,
门卫说要海底世界票,不会吧,我买的通票啊,门卫说不着急,又把我送回通票售票处(CAS server),通票售票处(CAS server)一看,发现我有TGC,嘿嘿,这家伙买过票了不用再买(不用再登录),于是换我一张票(ST)上面写着仅限海底世界使用,于是我就拿着这张票又去海底世界了。于是我明白了啥是SSO了,不就是把买票改成换票了吗?
比方完了,最开始的例子也就不往下继续了。需要注意的是系统A和B整合SSO需要把A、B的用户密码集中管理,你说A中我的用户名是张三,B中是李四,SSO能不能帮我自动识别,回答是不行的。
继续Acegi的整合。
CAS server是做用户密码验证,具体的权限授权的工作还是在各个单个系统里,也不应该交给它管。做用户密码验证需要AuthenticationHandler。这个具体就是根据Credential返回一个boolean值来判断你输入的用户密码正不正确。acegi提供了一个实现。
以一个典型的web访问来说明整个过程
1、用户访问一个受acegi安全保护的页面或业务方法;
2、用户没有登陆的话显然会抛出AuthenticationException
3、配置exceptionTranslationFilter捕获这个异常重定向到CAS server登陆页面
       <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
            
<property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
        
</bean>
        
        
<bean id="casProcessingFilterEntryPoint" class="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
            
<property name="loginUrl"><value>https://my.company.com/cas/login</value></property>
            
<property name="serviceProperties"><ref local="serviceProperties"/></property>
        
</bean>
        
        
<bean id="serviceProperties" class="org.acegisecurity.ui.cas.ServiceProperties">
            
<property name="service"><value>https://server.company.com/myapp/j_acegi_cas_security_check</value></property>
            
<property name="sendRenew"><value>false</value></property>
        
</bean>
serviceProperties里的service属性即在CAS server登陆完毕后由CAS server重定向回来的页面
  https://my.company.com/cas/login?service=https%3A%2F%2Fserver.company.com%2Fmyapp%2Fj_acegi_cas_security_check
4、CAS server检查是否有TGC ,没有则登陆,登陆后返回。这里屁股后面跟着的即ST,TGC通过cookie一并发送到客户端。
   https://server.company.com/myapp/j_acegi_cas_security_check?ticket=ST-0-jhsdfguwgeds
5、配置casProcessingFilter来处理返回ST(和以前的authenticationProcessingFilter比较类似)
   <bean id="casProcessingFilter" class="org.acegisecurity.ui.cas.CasProcessingFilter">
        
<property name="authenticationManager"><ref local="authenticationManager"/></property>
        
<property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
        
<property name="defaultTargetUrl"><value>/</value></property>
        
<property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
    
</bean>
6、配置authenticationManager
   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      
<property name="providers">
         
<list>
            
<ref local="casAuthenticationProvider"/>
         
</list>
      
</property>
   
</bean>
   
  
<bean id="casAuthenticationProvider" class="org.acegisecurity.providers.cas.CasAuthenticationProvider">
        
<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>
        
<property name="casProxyDecider"><ref local="casProxyDecider"/></property>
        
<property name="ticketValidator"><ref local="casProxyTicketValidator"/></property>
        
<property name="statelessTicketCache"><ref local="statelessTicketCache"/></property>
        
<property name="key"><value>my_password_for_this_auth_provider_only</value></property>
    
</bean> 
具体作用的是casAuthenticationProvider,casAuthenticationProvider通过 casProxyTicketValidator来校验ST
    <bean id="casProxyTicketValidator" class="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
        
<property name="casValidate"><value>https://my.company.com/cas/proxyValidate</value></property>
        
<property name="serviceProperties"><ref local="serviceProperties"/></property>
    
</bean> 
casProxyTicketValidator又具体实现调用了CAS Client library里的ProxyTicketValidator校验ST,ProxyTicketValidator 就比较有意思了,它做了个HTTPS请求CAS server,结果还是CAS server来校验ST(绕了一大圈)
 https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver.company.com%2Fmyapp%2Fj_acegi_cas_security_check
 重新回到CAS server,它接受到这个HTTPS请求,检查ST是否与对这个service发行的ST吻合,吻合的话CAS server就会发回一个肯定的XML回复,里面包含了用户名(username)。剩下的就EASY了,casProxyTicketValidator解析XML,casProxyDecider处理代理,casAuthoritiesPopulator根据解析后的XML获得user,最后就是casAuthenticationProvider构造Authentication(这里是CasAuthenticationToken)
7、重新回到casProcessingFilter,它将Authentication放入HttpSession
这样就完成了整个过程
posted @ 2006-08-29 12:31 ronghao 阅读(6253) | 评论 (5)编辑 收藏
在web.xml中一般我们这样配置:
    <filter-mapping>
        
<filter-name>Acegi Filter Chain Proxy</filter-name>
        
<url-pattern>/*</url-pattern>
    </filter-mapping>
这样agegi就对所有的url进行了过滤检查,以一个显示树状菜单为例,它甚至对页面上的每一个图片连接都进行了检查,实际上这是完全没有必要,可以这样:
    <filter-mapping>
        
<filter-name>Acegi Filter Chain Proxy</filter-name>
        
<url-pattern>*.action</url-pattern>
    
</filter-mapping>

    
<filter-mapping>
        
<filter-name>Acegi Filter Chain Proxy</filter-name>
        
<url-pattern>*.ftl</url-pattern>
    
</filter-mapping>
呵呵,检查范围缩小了,可是登陆时系统报404错误,找不到/j_acegi_security_check,因为/j_acegi_security_check这个路径是agegi自己的,所以再增加一行拦截过滤就OK
    <filter-mapping>
        
<filter-name>Acegi Filter Chain Proxy</filter-name>
        
<url-pattern>/j_acegi_security_check</url-pattern>
    
</filter-mapping>
posted @ 2006-08-03 10:45 ronghao 阅读(1720) | 评论 (1)编辑 收藏
周末公司组织去北戴河旅游。闷热的天气、潮湿的空气,让人对海边充满向往。上次去海边已是十六年前了,没有记忆,只有发黄的照片,年幼的我,傻呵呵地笑。十六年前是父亲带我去的,一晃十六年,上个礼拜父亲学校放暑假带奶奶来北京却没有时间陪他们,请了一天假带妹妹去了石景山游乐园,然后是让女朋友带着去了趟八达岭,仅此而已,仅此而已。很是愧疚。
目的地是河北昌黎的黄金海岸。下午五点到达,到达后的第一件事:下海。海浪很大,不会游泳,和女朋友一起站在腰深的地方,泡海。一切都很商业化:厕所,一元;更衣室,一元;热水淋浴,五元;游泳圈,二十元。。。女朋友属于很怕水的那种,一看见海浪就往海边跑,我好点,只要不没过胸就好。很羡慕那些会游泳的人,远远的只能看见他们的一个头,一个黑点,在海里起伏。其实离海岸越远海水越平静,海浪都是靠近海岸的时候才突然变得猛烈起来的。生活,是不是也象这样呢?
晚上在海边的大排挡解决了晚饭问题。和女朋友一起去买点东西,价格自然是高。她想吃袋饼干,一问价格,八元!于是划价,六元。朋友表示不可接受,店老板表示不可再让。于是向外走,走到门口的时候,店老板突然说,五元!于是又回去四点五元成交。生意都是不断妥协做成的。
出发前公司租了帐篷,晚上在海边扎帐篷过夜。真是很奇妙的感觉:外边海浪打在沙滩上发出巨大的声响,帐篷里却是异常的安静。静静地躺在那里,想到了很多的东西。想到了自己的童年,想到了自己的父母,想到了自己的工作,想到了自己的未来。想的最多的还是自己的未来,未来会是什么样子呢?想起刚到北京找工作那会,经过一家麦当劳门口,巨大而明亮的落地窗户后,一个年轻的女孩子,吃着炸薯条,仰起她那张无忧无虑的脸。
早上退潮了,朋友兴奋地去海滩上捡贝壳。有渔民过来买螃蟹,刚早上六点,他们已经出海回来了。是个晴天。
生活本来是很简单的,是不是自己把它搞复杂了?
posted @ 2006-07-16 16:40 ronghao 阅读(400) | 评论 (0)编辑 收藏

一、             考虑实现

1、  系统权限考虑继续采用原先实现方式,在构造功能树和树状菜单时作出权限判断;

2、  数据库操作权限考虑应用 Acegi 扩展,在业务层对相应的浏览 / 增加 / 修改 / 删除的业务方法进行拦截;

3、  行级数据权限考虑采用 AOP 的方式在用户访问相关资源时根据用户权限动态构造 SQL 注入到业务方法里,再由业务方法传递到 DAO 里;

4、  列级数据权限考虑做入页面,这里不再讨论。

5、  大集中模式下的权限管理,本质也是行级数据权限,即在每次数据访问时都需要强制判断用户所属部门 Group

一、 权限管理详细解决方案

用户、用户组、角色设计如下:
Image00000.bmp

Principal 即为权限主体

1、  系统权限授权

web 页面:

页面上显示两棵树:左侧显示用户、用户组和角色树,右侧显示功能模块树,功能模块树的节点上跟两个复选框,分别是可见 / 可再授权。点击用户、用户组和角色树上的节点对相应权限主体进行授权。

很显然可再授权权限包含可见权限。

数据库实现:

ACL 实现,表设计如下:

资源 ID ,权限主体 ID ,权限主体 TYPE ,资源 TYPE ,资源操作权限,条件查询语句 queryStr

说明:

权限主体 TYPE  三种: user/group/role

资源 TYPE         两种: function/method  此时对系统权限来说是 function

条件查询语句 queryStr    数据范围控制   此时对系统权限该字段无效

对象:
Image00002.bmp

用户保存授权信息时,先删除该权限主体 ID 的授权记录,再更新。

2、  数据库操作权限授权

这里引入一个新的对象:数据库操作资源对象   DataResource

表设计如下:

ID NAME parentId resStr resType desc

说明如下:

ID

NAME 资源名称 例如:新增用户

parentId

resStr  业务方法地址 例如: com.way.sevice.UserService.addUser

resType 资源类型,分两种: abstract/detail  抽象 / 具体

desc  描述说明

例子:

对用户管理进行数据库操作权限授权

新建“用户管理”做父节点,选择资源类型为“抽象”

在“用户管理”下再依次新增“新增用户”、“浏览用户”、“修改用户”、“删除用户”四个子节点,选择资源类型为“具体”

如果系统自己来判断存储就是叶子节点是“具体”,其他为“抽象”

web 页面:

页面上显示两棵树:左侧显示用户、用户组和角色树,右侧显示数据库操作资源对象树,数据库操作资源对象树的叶子节点的一级父节点上跟一个数据范围限定 button ,点击后弹出窗口输入限定条件;叶子节点上跟一个复选框。点击用户、用户组和角色树上的节点对相应权限主体进行授权

授权信息存入 ACL 表中

资源 TYPE method

3、  行级数据权限授权

已在上面做了说明即数据范围限定

4、  大集中模式下的权限授权

其实所谓大集中模式控制的也不过是数据范围,考虑是所有相关表全部增加 groupId 字段,新增时添入该字段,读出时进行判断

web 页面:

“组织和用户管理”模块中,每个组织中都允许设定一个管理员,一旦设定管理员,该组织就进入大集中模式,即所有该组织的数据与其他同级组织互相隔离,仅上级组织可见。同时说明一点的是:该管理员与系统总的管理员权限一样,不同的是数据范围仅限制与该组织内部。

综述:

实际的授权部分采用了 ACL ,所以授权比较简单和直观

系统资源和数据库操作资源分开两个表存储,这样可能会给用户带来不便,也就是授权时还需要切换,但这种不便似乎不好解决,因为一个是粗粒度的一个是细粒度的。

Image00001.bmp

posted @ 2006-07-06 17:47 ronghao 阅读(3009) | 评论 (0)编辑 收藏
仅列出标题
共39页: First 上一页 28 29 30 31 32 33 34 35 36 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

关注工作流和企业业务流程改进。现就职于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

常用链接

留言簿(38)

随笔分类

随笔档案

文章分类

文章档案

常去的网站

搜索

  •  

最新评论

阅读排行榜

评论排行榜