问题的提出:我们的需求是什么?
首先是系统中需要哪些权限。
权限应该分类四类:
一是系统方面,主要是对模块的权限划分 ,具体就是可见不可见,用户能不能对该模块进行再授权
二是数据库操作权限,主要是浏览、增加,修改,删除记录,也可以理解为对象权限
三是行级数据权限,又可以叫做对象实例级权限,主要是考虑到不是每个用户都可以看到所有记录的,比如在工资管理中一个部门用户就只能看到本部门人员的工资,甚至只能看到本部门什么职位以下的人员的工资。
四是列级数据权限,即数据字段的权限,不是每个用户都可以看到或是修改所有的字段的。
具体四类可能的权限划分如下:
一系统权限,可见/可再授权
二数据库操作权限,浏览/增加/修改/删除
三行级数据权限,数据范围
四列级数据权限,可见/修改
然后是可能存在的权限模式,现在考虑的是大集中模式下的权限管理
理解:什么是大集中模式下的权限管理。举个例子总公司下面有分公司A和分公司B,总公司系统管理员分别在分公司A和分公司B中设定分公司系统管理员,则分公司A和分公司B数据是互不可见的,分公司系统管理员只对各自分公司负责,他们可以同时建立一个相同名字的角色,但这两个角色是不同的。即下级只可以看到自己,上级可以看到所有。这个管理是可以嵌套的,即分公司A下面可能还会存在分公司,分公司下面还会有新的分部门。。。。
posted @
2006-07-03 10:50 ronghao 阅读(3959) |
评论 (5) |
编辑 收藏
最近在设计权限方面的内容,有些想法,乱弹一下。个人觉得实现权限系统主要是三个方面:
1、授权。主要是授权模型的维护,如资源、角色、用户、部门的对应关系等。
2、认证。主要是用户身份的认证,以及取出用户的权限。
3、校验权限。当用户对某一资源进行操作时,将用户的权限与操作该资源所应有的权限进行比对校验。
在对这三个方面进行说明前,也想说说对数据权限的看法。什么是数据权限,很简单,
考虑一种场景 (javaeye里的例子)
看看销售数据
A销售员可以看到自己的销售情况和每一笔具体销售业务,但是看不到B的
B销售员可以看到自己的销售情况和每一笔具体销售业务,但是看不到A的
分公司销售经理则可以看到本部门的A和B的销售情况,但是看不到其他分公司的销售业务
集团销售Boss可以看到集团内所有分公司的销售业务数据
共同点:他们都可以看到“销售数据”这一模块
不同点:他们读取数据的范围是不一样的
这个也可以叫做实例级权限控制。有人认为这种权限一般是放在业务里做的, 如果非要用一个固定的模型实现,可以参考 ACL, 不过也是要在业务里写 ACL 相关代码的。确实,以前自己也都是放在业务里做的,但一直认为这也应该是权限系统的一部分,通过用户的权限来构造不同的sql语句。具体通过AOP实现,好象已经有个开源的东西还没看(lllyq的
http://bba96.dev.java.net)。ACL对实例级权限控制感觉效率会有问题,个人看法。
具体来说:
1、授权
具体开发里简便的授权方式已经成了用户必提的要求,很明显,仅仅基于role和权限交互是远远不够的。现实中你必须把角色、用户、部门三者全部与权限挂钩。而这三者毫无疑问地就会存在权限继承的问题。考虑一下,在部门A增加一个用户,很显然该用户会继承部门A的权限;同时如果在部门A下增加一个部门角色,该角色应不应该也继承部门A的权限呢?也许需要一个规则接口,具体规则实现看客户需求。
再说说资源,这里仅讨论系统资源不考虑数据资源。考虑一个“业务管理”的模块,该模块下面还有“项目管理”,“物品管理”,“采购管理”三个模块,当对用户赋予了“业务管理”模块的查看权限,用户是否同时对“项目管理”,“物品管理”,“采购管理”具有查看权限呢?这里同样存在资源权限继承的问题。客户的需求是不同的,所以同样需要一个资源权限继承的规则接口。
最后说说授权信息的保存。考虑ACL。表设计:资源ID,权限主体ID,权限主体TYPE,资源操作权限。一开始考虑权限主体ID就是UserID,这样会在认证的时候效率很高,但考虑到部门A下有100个用户,当对部门A增加一个权限时,实际上会往ACL表里插入100条记录,这就让人不能接受了。
2、认证
其实就两个方面,一是检查是否存在这个用户,二是取出用户的权限。呵呵,这里有些绝对了,取出用户的权限完全可以放到校验权限里来做,不必这里一次性全读出来。用户的权限放在一个List里,对象可以构造一个,两个属性:资源ID和资源操作权限。取出用户的权限时候要用到上面定义的规则接口来组装用户实际的所有权限。
2、校验权限
这个就比较简单了,个人倾向于在Action里完成这个工作,需要进行权限检查的Action实现一个接口,接口里有一个 public boolean hasPermission() ,写个拦截器拦截即可。这里的关键还是通过资源权限继承的规则接口来校验用户操作该资源的权限。
完全是个人乱弹,欢迎拍砖:)
posted @
2006-06-29 16:29 ronghao 阅读(3621) |
评论 (2) |
编辑 收藏
开发中遇到这么一个要求,用户USER这个PO里需要保存用户的照片。一般情况下有两种处理方法:一是直接保存图片到数据库;二是保存图片到服务器端,PO字段保存一个联接。考虑到用户照片一般较小,采用第一种方法。
1
public
class
User
extends
Principal
{
2
private
byte
[] photo;
//
考虑与各种数据库兼容问题
3
public
byte
[] getPhoto()
{
4
return
photo;
5
}
6
7
public
void
setPhoto(
byte
[] photo)
{
8
this
.photo
=
photo;
9
}
10
..
11
}
12
页面里面,直接用webwork的FileUploadInterceptor拦截
<
@ww.form enctype
=
"
multipart/form-data
"
action
=
"
doUpdateUser
"
method
=
"
post
"
>
<
image name
=
"
img1
"
src
=
"
/getUserPhoto.action?userId=${user.id}
"
width
=
90
height
=
120
border
=
"
0
"
></
image
>
<
@ww.file label
=
"
%{getText('user.photo')}
"
name
=
"
photo
"
/>
</
@ww.form
>
xwork.xml里的配置
<
action name
=
"
doUpdateUser
"
class
=
"
com.ronghao.organization.action.OrganizationAction
"
method
=
"
updateUser
"
>
<
interceptor
-
ref name
=
"
defaultStack
"
>
<
param name
=
"
fileUpload.allowedTypes
"
>
image
/
x
-
png,image
/
gif,image
/
pjpeg
</
param
>
</
interceptor
-
ref
>
<
result name
=
"
success
"
>/
organization
/
user.ftl
</
result
>
</
action
>
<
action name
=
"
getUserPhoto
"
class
=
"
com.ronghao.organization.action.OrganizationAction
"
method
=
"
getUserPhoto
"
>
<
result
>/
organization
/
user.ftl
</
result
>
</
action
>
引用默认的拦截器栈,栈里已经包含FileUploadInterceptor拦截,这里配置FileUploadInterceptor拦截的参数,设定上传的文件为图片
格式
Action类
1
public
class
OrganizationAction
extends
BaseOrganizationAction
{
2
private
File photo;
//
与页面里的上传文件字段名对应
3
private
OutputStream outPhoto
4
5
/** */
/**
6
* 更新用户信息
7
*
8
*
@return
9
*
@throws
Exception
10
*/
11
public
String updateUser()
throws
Exception
{
12
//
以下为保存图片,视情况修改
13
if
(
null
!=
photo)
{
14
FileInputStream file
=
new
FileInputStream(photo);
15
int
length
=
file.available();
16
byte
[] buffer
=
new
byte
[length];
17
file.read(buffer);
18
file.close();
19
user.setPhoto(buffer);
//
将上传的图片转换为字节数组存储到PO中
20
}
21
organizationService.updateUser(user);
22
return
SUCCESS;
23
}
24
25
public
String getUserPhoto()
throws
Exception
{
26
user
=
organizationService.getUserById(userId);
27
if
(user.getPhoto()
!=
null
)
{
28
outPhoto
=
this
.getResponse().getOutputStream();
//
将PO中字节数组转换为输出流
29
outPhoto.write(user.getPhoto());
30
outPhoto.flush();
31
outPhoto.close();
32
}
33
return
SUCCESS;
34
}
35
}
36
这样就OK了,考虑一个问题,就是action 必须要指定一个result ,实际这里的图片显示仅仅是要一个输出流
<
image name
=
"
img1
"
src
=
"
/getUserPhoto.action?userId=${user.id}
"
width
=
90
height
=
120
border
=
"
0
"
></
image
>
而我的配置里面是
<
result
>/
organization
/
user.ftl
</
result
>
不知道这会不会有什么影响。或者这样?
<
result
>/
organization
/
blank.ftl
</
result
>
posted @
2006-06-15 17:14 ronghao 阅读(659) |
评论 (0) |
编辑 收藏
好久都没有更新过BLOG了,别的原因没有,就是变懒了。工作还算可以,加班不是太多。买了辆二手
自行车,修车就花了20,天天蹬着车往返于公司和家之间。又有新的楼盘开盘了,价格还是高得吓人,
女朋友天天想着什么时候住上自己的房子,真是一件苦恼的事情。油价涨了我还有腿,可房价涨了呢?
在对自己重新补课,现在确实感到一些东西你不记下来忘得还是飞快的。节绳记之还是必须的。呵呵,
重新开始写BLOG吧。
posted @
2006-06-11 14:22 ronghao 阅读(379) |
评论 (0) |
编辑 收藏
来博罗调研已经是第七天,后天的机票返回北京。短短的几天给我的印象却非常的深。
这是我第一次出差调研和客户打交道,习惯了面对机器,习惯了每天的编码,或许自己从来没有料到自己会出来面对人来交流。出公司的时候,领导说这是一次难得的锻炼机会,现在来看确实是这样。
印象一:工厂
项目是广东惠州市博罗县的电子政务。从深圳机场出来到惠州,沿路两旁全部是厂房和宿舍,一片接着一片,多得让人吃惊,车子在高速路上飞驰,看不见田野,看到的是山是楼房。司机开玩笑说,我敢说你穿的衣服一定有一件产自广东。人说中国是世界的工厂,那广东一定是中国的工厂。
印象二:喝汤
第一顿饭是在县机关饭堂吃得。吃饭前先给打来了一盆汤,喝汤。习惯了吃完饭喝汤,这里却是先喝汤再吃饭。以后在哪里吃饭都是这样,先上汤,喝得差不多了再上菜。再就是早上出去吃早饭,没有豆浆,没有油条,更没有包子,只有米线。第二天早上跑了大半个街道,不好意思,只有米线。
印象三:乱
这个乱不是指这里的治安,指得是调研。其实在我来之前,公司已经有过两次前期的调研,大致的需求已经清楚,我们所做的事把需求进一步完善,五一后就开始正式开发。情况出乎我的意料,非常的不顺利。在对工作流的演示完毕后,各种各样的情况就来了:我们的领导不会打字,你们要想想办法;流程已经到下一个流程,上一个流程节点的人员可不可以强行把流程回退。种种情况让我感到迷惑。很多概念都要解释很长一段时间。总的感觉就是:人为干扰流程的因素太多,流程迟迟定不下来。然后就是发言的人特多,几乎都是同时。其实这里也有很大一部分责任在于自己:没有对客户做好引导,他们的
思维还是停留在他们自己的日常办公上。OA的实施不仅仅是我们要适应他们,他们也要适应一定的规范。对客户如何引导,我想,这对我来说还是一个要好好思考的问题。
印象四:累
其实来广东之前已经连续加了一个多礼拜班了。想着是这次调研会轻松一些,甚至还带了XML的书,打算把这方面补一补,不都web2.0了吗:)结果却是比编程感觉更累。白天和客户交流,中午和晚上一有空就要写文档,每天晚上都到12点,中午就没有休息过。写文档真是一件枯燥而又繁重的工作。每一个button都要作出详尽的描述,让人气馁。而流程的描述更是繁琐几乎要面面俱到,中间还有权限的分配。情况却往往是这样:客户提出的流程很快发生了变化。还有就是,文字的描述要符合官方的习惯。例如,县委就一定要在县政府的前面。这点自己也是一直并未在意,但客户就提意见了。
最后,就是,广东话我一句都听不懂,呵呵。
posted @
2006-04-26 19:40 ronghao 阅读(456) |
评论 (0) |
编辑 收藏