一个struts1+spring+hibernate的典型权限系统的设计思路,归纳小结如下,特别适用于简单场合的,比如某个单位下,有直属单位及部门的
情况.数据表设计如下
user表:
userid:
username:
unitid: //所属单位的id
deptid://所属部门的id
status:0表示为普通用户 1:表示为该单位的最高管理员
role角色表
id:编号
rolename:角色名
content:角色的具体分配权限
memo:备注
unit:所属的单位id
userright表:(user与role是多对多,因此需要该表)
id:
userId:
roleid:
unit表(单位表)
unitId:单位编号
unitName:单位名
fatherId:上级单位ID (如果为0的时候,表示为最上层的单位)
allFatherId:保存所有关联的父级单位的id路径)
unitType :表明是单位还是部门, 0:单位, 1:部门
举个例子说明下:
unitid unitname fatherid allfatherid unittype
1 根单位 0 0
2 根单位部门1 1 ,1 1
3 直属单位1 1 ,1 0
4 直属单位1的部门1 3 ,1,3 1
AddressGroup 单位群组表:这个表的作用在于,可以将某几个单位归为一个群组,那么比如在发文的时候,可以一次同时发送文件给该群组下的
所有的单位
groupId 群组编号:
groupName 群组名称
content:包含的单位id,比如某个群组有单位1,3的
二 在页面层中,类似如下:
<td rowspan=4>发文管理</td>
<td><input name="box" type="checkbox" value="211">发文登记</td>
<td><input name="box" type="checkbox" value="212" >创建</td>
<td><input name="box" type="checkbox" value="213" >修改</td>
<td width=15%><input name="box" type="checkbox" value="215" >查看</td>
.......就是很多个上面的形式,
然后用javascript把用户所选的都记录下来
function check(){
if (thisForm.roleName.value == ""||trim(thisForm.roleName.value)==""){
alert("请填写角色名称!");
thisForm.roleName.focus();
return false;
}
thisForm.content.value=getRole();
thisForm.submit();
}
//将角色用逗号连接起来
function getRole(){
var allCHK = document.body.all.tags('INPUT');
var lstr = "" ;
for(i=0;i<allCHK.length;i++){
if(allCHK[i].type.toUpperCase()=="CHECKBOX" && allCHK[i].checked==true){
if (lstr==""){
lstr = allCHK[i].value;}
else {lstr= lstr + "," + allCHK[i].value; }
}
}
return lstr ;
}
同样要埋藏一个hidden域来保存咯
<input type=hidden name=content value="$!role.getContent()">
三 action层的保存
/**
* 保存角色信息
*/
public void saveRole(Role role)throws Exception{
String where = " from Role where roleName='"+role.getRoleName()+"' and unitId = "+role.getUnit().getUnitId()+" and roleId<>"+role.getRoleId();
List list = roleDao.find(where);
if(list.size()>0){
throw new LogicException("本单位中已经存在" + role.getRoleName() + "这个角色");
}
roleDao.save(role);
}
四 编辑角色时,把某个角色读取出来,回显在页面上
public ActionForward viewRole(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response){
String roleId = request.getParameter("roleId");
if(!("".equals(roleId))){
Role role = roleManager.getRole(roleId);
request.setAttribute("role",role);
}
return mapping.findForward("viewRole");
}
在JSP页面中,可以读出来 ,可以在body的onload函数中,读init();
<input type=hidden name="content" value="$!role.getContent()">
function init(){
var allCHK = document.body.all.tags('INPUT');
var content = thisForm.content.value;
if(content != ""){
var strIds = content.split(",");
for(k=0;k<strIds.length;k++){
for(i=0;i<allCHK.length;i++){
if(allCHK[i].type.toUpperCase()=="CHECKBOX" && allCHK[i].name=="box" && allCHK[i].value==strIds[k]) {
allCHK[i].checked=true ;
}
}
}
}
}
五 权限的判断
一般在一个菜单里面,可以在导航菜单中予以体现
下面是velocity的一个例子
#set ($RECVDOC_LIST = 111)
#set ($RECVDOC_SIGN = 112)
#set ($RECVDOC_TUIHUI = 113)
#set ($RECVDOC_READ = 114)
#set ($RECVDOC_LOOKFOR = 115)
就是设定某些功能的权限编码
然后是service层的,取出某个用户的权限:
public Vector getPermissionIDsByUserId(int userId) throws Exception{
int i;
Vector v=new Vector();
String sql=" from Role where roleid in (select roleId from UsersRight where userId="+userId+")";
List list = roleDao.find(sql);
Iterator iter = list.iterator();
while(iter.hasNext()){
Role role = (Role)iter.next();
String strIds[] = StringUtils.split(role.getContent(),",");
for(i = 0; i < strIds.length; i++){
v.add(strIds[i]);
}
}
return v;
}
}
public boolean hasPermission(int permissionId) throws Exception{
String permissionIdStr=Integer.toString(permissionId);
boolean retValue = false;
if(permission == null) {
//返回该用户的权限
permission = rmg.getPermissionIDsByUserId(u.getUserId().intValue());
}
if(permissionIdStr.length()==3){ retValue=permission.contains(permissionIdStr);}
if(permissionIdStr.length()==1)
{
int i;
for(i=0;i<permission.size();i++)
{
if (((String)permission.elementAt(i)).startsWith(permissionIdStr))
{
retValue=true;
i=permission.size();
}
}
}
return retValue;
}
菜单拦的判断
var p;
#if($userinfo.hasPermission(1))
p = new createPanel('recvdoc','收文管理');
#if($userinfo.hasPermission($RECVDOC_SIGN_LIST) || $userinfo.hasPermission($RECVDOC_SIGN_PRINT) || $userinfo.hasPermission($RECVDOC_SIGN_READ) || $userinfo.hasPermission($RECVDOC_SIGN_LOOKFOR))
p.addButton('$request.getContextPath()/menu/images/recvdoc.gif','待签收文件','changePage("10");');
#end
比如上面的收文管理模块中,有很多个子功能,这里首先传入到userinfo.hasPermission(1))去判断,
这时会执行if(permissionIdStr.length()==1)
{
的判断,
假如该用户有收文管理下的某个子功能的权限,比如111,则通过该验证(注意 i=permission.size();跳出FOR了,返回true值,因此该
用户可以看到"收文管理"这个大的菜单,至于该用户能具体看到下面的哪些子功能,则通过
if(permissionIdStr.length()==3){ retValue=permission.contains(permissionIdStr);} 去判断了.