|
这个主题共有 23 回复 / 2 页 [
1 2
下一页
]
|
|
|
|
|
|
在jsp web项目中实现透明的权限控制
|
发表: 2003年09月24日 11:12
|
回复
|
|
现在想到的是在Filter中做……
目标:通过配置来实现权限管理,在业务代码中无需再考虑权限问题 参考:类似tomcat的realm,在进到项目前,已经由容器判断了权限。权限管理通过配置来实现,在业务代码中无需再考虑权限问题。不足是,servlet规范中用URL Pattern配置访问级别,不够灵活 办法:在Filter中做权限判断? 我做了一个接口boolean isUserHasPerm(String user, String url)
MyFilter调用接口 if (!isUserHasPerm(...)) response.sendError(403, "Forbidden");
isUserHasPerm接口已经初步实现,???现在的问题是Filter好像不是放权限判断的地方???,因为签名是这样的: public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
其中request 是ServletRequest, 不是HttpServletRequest, response是ServletResponse,不是HttpServletResponse 这样就没有request.getSession().getAttribute("userinfo"),//得到权限判断的who要素 没有response.sendError() //这样没有权限,该如何处理? ???当然可以强行转换,tomcat下也不会cast错误,但始终不是个办法……???
----------------------------------------------- 另外,说明一下isUserHasPerm的实现 相关联的对象图

核心是ACL表,实际操作给出role,function,resource三要素,如果ACL表中有记录,说明可以访问,因为三要素唯一确定一条ACL记录(function通过resoure type和operate type确定)
优化后,剩三个表,User,Role,ACL(当然,因为User,Role是多对多,还要一个关联表) ACL表包含四个字段: Role, Component, Instance, OP(参考了PostNuke的权限设置) Component就是resource type, Instance就是resource OP就是function
合并进Component和OP,而不是functionID的好处是,可以通过通配符来设置权限,比如设置一个全局的管理权限,只需要一条记录 role=admins, component=*, instance=*, OP=*
另外,OP字段还可以等于DENY,有优先权,如果找到一条匹配的DENY记录,直接就是没有权限了。有了DENY,如果需要赋大部分权限,排除一小部分,也比较容易配置
isUserHasPerm的伪码 (1) select * from ACL where Role in (user.getRoles()) and Component in (url.getComponent, *) and Instance in (url.getInst, *) and OP = DENY
(2) if (结果集>=0) return false;
(3) 将(1)的OP条件改为 and OP in (url.getOP, *)
(4) if (结果集>0) return true; else return false;
*注:从url中得到权限判断的要素,当然需要一些规则了,比如 category.do?op=add&id=1 表示component是category op是add instance是1 role当然是从session中拿
|
|
|
|
|
|
Re: 在jsp web项目中实现透明的权限控制
|
发表: 2003年09月24日 15:44
|
回复
|
|
稍微看了一下,如果我的意见和事实不符合请见谅。
我觉得用filter来执行权限判断是不可能的,因为基于数据库应用的URL经常是一致的,只是后面的参数不一样。有些参数还是表单发送的。 所以,用它来执行中文化是不错的,但是来实现ACL功能好象不行,tomcat可以是因为它的各部分是不同的URL吧。
我觉得windows2000的许可和角色和树状继承很不错,不过在应用中实现还是有难度。
|
|
|
|
|
|
Re: 在jsp web项目中实现透明的权限控制
|
发表: 2003年09月24日 16:31
|
回复
|
|
filter概念实际就是Proxy模式实现。
ACL是肯定要用Proxy模式实现,关键是如何实现比较巧妙,象Jive那样,为每个数据Model建立Proxy(filter)的做法是不可取的,动态Proxy好像是比较好的方法,根据操作方法名称,如果get,表示读取操作,update表示更新,缺点是,要求对EJB或Service操作方法实现统一命名限制。
通过EJB容器的安全机制,在EJB-jar.xml中配置ACL也是目前比较好的办法,缺点是需要管理员修改EJB-jar.xml,那么在此基础上,编制管理程序操作修改EJB-jar.xml可以达到方便ACL设置吧。
|
|
|
|
|
|
Re: 在jsp web项目中实现透明的权限控制
|
发表: 2003年09月25日 09:27
|
回复
|
|
>只是后面的参数不一样。有些参数还是表单发送的。 其实在filter中传入的参数是request,参数可以通过getRequestURI,getParameter来获取,
问题是如何通过request提取出 role,component,instance,op, 这个规则不太好定: 能要求URI就是component? instance一定要用名为id的parameter来确定? 要显式的给出op参数?
而且,定了这样的规则,方案就不透明了
|
|
|
|
|
|
一、数据库
|
发表: 2003年09月25日 13:33
|
回复
|
|
下面给出isUserHasPerm的初步实现
一、数据库,mssqlserver
drop table hive_acl; drop table hive_account_role; drop table hive_account; drop table hive_role;
create table hive_account ( id int identity, account varchar(50) unique not null, password varchar(16) not null, primary key (id), );
create table hive_role ( id int identity, role varchar(50) unique not null, primary key (id), );
create table hive_account_role ( account_id int, role_id int, primary key (account_id, role_id), foreign key (account_id) references hive_account(id), foreign key (role_id) references hive_role(id), );
create table hive_acl ( role_id int, component varchar(50), instance varchar(50), op varchar(50), primary key (role_id, component, instance, op), foreign key (role_id) references hive_role(id), );
insert into hive_account (account, password) values ('admin', 'abc'); insert into hive_account (account, password) values ('amen', 'abc'); insert into hive_account (account, password) values ('anonymous', '');
insert into hive_role (role) values ('admins'); insert into hive_role (role) values ('users'); insert into hive_role (role) values ('guests');
insert into hive_account_role (account_id, role_id) values (1,1); insert into hive_account_role (account_id, role_id) values (1,2); insert into hive_account_role (account_id, role_id) values (2,2); insert into hive_account_role (account_id, role_id) values (3,3);
insert into hive_acl (role_id, component, instance, op) values (1, '*', '*', '*'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', 'manager', 'none'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', '*', 'read'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', 'public', 'write'); insert into hive_acl (role_id, component, instance, op) values (3, 'category', 'public', 'read');
|
|
|
|
|
|
二、两个测试的sql语句
|
发表: 2003年09月25日 13:40
|
回复
|
|
测试权限的核心语句,其实后面的java方法只是另一种实现 1) 查询相应的op=none的记录,如果记录数大于则没有权限 2) 查询匹配记录,如果记录数等于0(没有acl记录)则没有权限
-- 判断是否有op=none的acl记录 declare @account varchar(50); declare @component varchar(50); declare @instance varchar(50); declare @op varchar(50);
select @account = 'anonymous'; select @component = 'category'; select @instance = 'manager'; select @op = 'write';
select * from hive_acl where role_id in ( select role_id from hive_account_role inner join hive_account on hive_account_role.account_id = hive_account.id where account = @account ) and component in (@component, '*') and instance in (@instance, '*') and op ='none' ;
-- 判断是否有匹配的acl记录 declare @account varchar(50); declare @component varchar(50); declare @instance varchar(50); declare @op varchar(50);
select @account = 'amen'; select @component = 'category'; select @instance = 'manager'; select @op = 'write';
select * from hive_acl where role_id in ( select role_id from hive_account_role inner join hive_account on hive_account_role.account_id = hive_account.id where account = @account ) and component in (@component, '*') and instance in (@instance, '*') and op in (@op, '*') ;
|
|
|
|
|
|
三、PermissionManager接口
|
发表: 2003年09月25日 13:42
|
回复
|
|
将由filter调用
public interface PermissionManager {
public boolean isUserHasPerm(HttpServletRequest request);
}
|
|
|
|
|
|
四、PermissionFilter
|
发表: 2003年09月25日 13:45
|
回复
|
|
public class PermissionFilter implements Filter { public void doFilter( ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
try { HttpServletRequest req = (HttpServletRequest)request; if (!HiveFactory.getDefaultHive().getPermissionManager().isUserHasPerm(req)) { HttpServletResponse rep = (HttpServletResponse)response; rep.sendError(403); }
} catch (Exception e) { }
try {
filterChain.doFilter(request, response); } catch (Exception e) { } } }
|
|
|
|
|
|
五、PermissionManager的实现
|
发表: 2003年09月25日 13:47
|
回复
|
|
public class PermissionManagerImpl implements PermissionManager {
public boolean isUserHasPerm(HttpServletRequest request) { HttpSession session = request.getSession(); Account user = (Account)session.getAttribute("userinfo"); if (user == null) user = HiveFactory .getDefaultHive() .getUserManager() .getAnonymousUser();
String component, instance, op; // get component from URI { String uri = request.getRequestURI(); int i, j; i = uri.lastIndexOf("/"); j = uri.indexOf(".do", i); component = uri.substring(i+1, j).toLowerCase(); } // get instance instance = request.getParameter("id"); // get op op = request.getParameter("op"); return isUserHasPerm(user.getAccount(), component, instance, op); }
private boolean isUserHasPerm( String account, String component, String instance, String op) { try { Connection cn = HiveFactory.getDefaultHive().getConnection(); if (cn == null) return false; String sql; PreparedStatement pstm; ResultSet rs; int count;
sql = "select count(*) from hive_acl" + " where role_id in (" + " select role_id" + " from hive_account_role inner join hive_account" + " on hive_account_role.account_id = hive_account.id" + " where account = ?" + " )" + " and component in (?, '*')" + " and instance in (?, '*')" + " and op ='none'"; pstm = cn.prepareStatement(sql); pstm.setString(1, account); pstm.setString(2, component); pstm.setString(3, instance); rs = pstm.executeQuery(); rs.next(); count = rs.getInt(1); if (count >= 1) { cn.close(); return false; }
sql = "select count(*) from hive_acl" + " where role_id in (" + " select role_id" + " from hive_account_role inner join hive_account" + " on hive_account_role.account_id = hive_account.id" + " where account = ?" + " )" + " and component in (?, '*')" + " and instance in (?, '*')" + " and op in (?, '*')"; pstm = cn.prepareStatement(sql); pstm.setString(1, account); pstm.setString(2, component); pstm.setString(3, instance); pstm.setString(4, op); rs = pstm.executeQuery(); rs.next(); count = rs.getInt(1);
cn.close(); if (count == 0) { return false; } return true;
} catch (SQLException e) { e.printStackTrace(); return false; } }
}
|
|
|
|
|
|
四.(1)、PermissionFilter的设置
|
发表: 2003年09月25日 13:52
|
回复
|
|
在web.xml中,PermissionFilter设置过滤"/secu/*"的请求
<web-app> <filter> <filter-name>permissionfilter</filter-name> <filter-class>com.stalent.hive.permission.PermissionFilter</filter-class> </filter> <filter-mapping> <filter-name>permissionfilter</filter-name> <url-pattern>/secu/*</url-pattern> </filter-mapping>
|
|
|
|
|
|
六、一些说明
|
发表: 2003年09月25日 13:58
|
回复
|
|
前面
insert into hive_acl (role_id, component, instance, op) values (1, '*', '*', '*'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', 'manager', 'none'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', '*', 'read'); insert into hive_acl (role_id, component, instance, op) values (2, 'category', 'public', 'write'); insert into hive_acl (role_id, component, instance, op) values (3, 'category', 'public', 'read');
前面insert的数据表示: 假想有一种“category”的资源(可以想象成目录、论坛的板块之类) 有public,manager以及其他的一些实例 role_id=1是admins,2是users,3是guests admins有所有权限 users可以读除manager外的所有资源,并对public可写 guests只能读public
|
|
|
|
|
|
七、测试
|
发表: 2003年09月25日 14:06
|
回复
|
|
以users登录 /hiveweb/secu/category.do?op=read&id=manager 403 Forbidden
/hiveweb/secu/category.do?op=read&id=public 400 Invalid path
……
|
|
|
|
|
|
八、请教如何改进设计
|
发表: 2003年09月25日 14:24
|
回复
|
|
一、没有owner的概念,比如要让用户对自己创建的资源有编辑权,怎么办?……
二、PermissionFilter,如果设为过滤"/*",又是根目录下的项目,tomcat启动时也会调用doFilter方法,这不是我想要的
三、PermissionFilter中,downcast ServletRequest到HttpServletRequest,会不会有隐患?上传文件通过mutipart form提交的request会不会转换错?还有没有其他不能cast的情况?
四、用资源类型、操作类型能唯一确定一个功能吗?
|
|
|
|
|
|
Re: 在jsp web项目中实现透明的权限控制
|
发表: 2003年09月25日 14:24
|
回复
|
|
可以参见 seraph http://opensource.atlassian.com/seraph
|
|
|
|
|
|
Re: 在jsp web项目中实现透明的权限控制
|
发表: 2003年09月25日 14:52
|
回复
|
|
Woo~ Seraph is a 'gate keeper' for J2EE applications - thus was named after Seraph from the Matrix Reloaded.
thumbup!;)
|
|
|
|
|
|
这个主题有 23 回复 / 2 页 [
1 2
下一页
]
|
|
|