现在的位置: 首页 > 综合 > 正文

RBAC权限管理的一点小改进

2013年02月26日 ⁄ 综合 ⁄ 共 8026字 ⁄ 字号 评论关闭

项目开始根据权限系统来控制目录和按钮了,为了读取和控制方便,需要把set里的权限列表变成map结构,用key来读取方便,很久以前做过个类似的,不过那时刚刚学习java,代码没有保留下来,所以这次记录下,以备日后查看。

关键代码和配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="cn.lh.posco.entity.management">
	<class name="Role" table="t_roles" mutable="true">
		<id name="id" column="ID" type="long">
			<generator class="native" />
		</id>
		
		<property name="system"		column="System"		type="boolean" />
		<property name="name" 		column="Name" 		type="string" />
		<property name="remark" 	column="Remark" 	type="text" />
		
		<set name="limits" fetch="join" cascade="all">
			<key column="Role_ID" />
			<one-to-many class="RoleLimit" />
		</set>
	</class>
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="cn.lh.posco.entity.management">
	<class name="RoleLimit" table="t_role_limits">		
		<composite-id name="id" class="cn.lh.posco.entity.component.RoleLimitID">
			<key-many-to-one name="role" 	class="Role" 								column="Role_ID" />
			<key-many-to-one name="model"	class="cn.lh.posco.entity.system.Model"		column="Model_ID" />
			<key-many-to-one name="method"	class="cn.lh.posco.entity.system.Method"	column="Method_ID" />
		</composite-id>
		
		<property name="enable" column="Enable" type="boolean"/>
	</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="cn.lh.posco.entity.management">
	<class name="Supervisor" table="t_supervisors">		
		<id name="id" column="ID" type="long">
			<generator class="native" />
		</id>
		
		<property name="enable" 	column="Enable"		type="boolean" />
		<property name="name"		column="Name"		type="string" />
		<property name="username"	column="Username"	type="string" />
		<property name="password"	column="Password"	type="string" />
		<property name="remark" 	column="Remark" 	type="text" />
		
		<many-to-one name="role" column="Role_ID" class="Role" fetch="join" />
	</class>
</hibernate-mapping>

supervisor , role和rolelimit ,还有Model和method两个实体:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="cn.lh.posco.entity.system">
	<class name="Model" table="t_models" mutable="false">
		<cache usage="read-only"/>
		
		<id name="id" column="ID" type="long">
			<generator class="native" />
		</id>
		
		<property name="menuable"	column="MenuAble"	type="boolean" />
		<property name="name"		column="Name"		type="string" />
		<property name="remark" 	column="Remark"		type="text" />
		
		<many-to-one name="parent" column="Parent_ID" class="Model" fetch="join" />
		
		<set name="children" fetch="join" mutable="false">
			<cache usage="read-only"/>
			<key column="Parent_ID" />
			<one-to-many class="Model" />
		</set>
		<set name="methods" table="t_model_methods" fetch="join" mutable="false">
			<cache usage="read-only"/>
			<key column="Model_ID" />
			<many-to-many class="Method" column="Method_ID"/>
		</set>
	</class>
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="cn.lh.posco.entity.system">
	<class name="Method" table="t_methods" mutable="false">
		<cache usage="read-only"/>
		
		<id name="id" column="ID" type="long">
			<generator class="native" />
		</id>
		
		<property name="menuable"	column="MenuAble"	type="boolean" />
		<property name="name"		column="Name"		type="string" />
		<property name="remark" 	column="Remark"		type="text" />
		
		<set name="models" table="t_model_methods" fetch="join" mutable="false">
			<cache usage="read-only"/>
			<key column="Method_ID" />
			<many-to-many class="Model" column="Model_ID"/>
		</set>
	</class>
</hibernate-mapping>

这些就是hbm文件了,可以看到,model是这个自连树的结构,可以有parent,也可以有children,以前的文章提到过hibernate双向关联时,hashcode和equals方法里不能出现双向关联的字段,原因是会无限递归,还有toString也是。

然后,根据项目,觉得变成Map<String , Map<String, Boolean>>,这样的结构比较容易使用,第一个String是TopMdel的name,第二个就是路径,Boolean就是是否有权限

实现算法

public void convertLimit2Map(Role role) {		
		Set<RoleLimit> limits = role.getLimits();
		Set<Model> topModels = getTopModels(limits);				
		Map<String , Map<String, Boolean>> limitMap = convertLimitMap(topModels , limits);
		
		ActionContext.getContext().getSession().put(Global.LONGIN_LIMITMAP, limitMap);
	}

private Map<String, Map<String, Boolean>> convertLimitMap(Set<Model> topModels, Set<RoleLimit> limits) {
		Map<String, Map<String, Boolean>> limitMap = new HashMap<String, Map<String,Boolean>>();
		
		for(Model topModel : topModels){
			String name = topModel.getName();
			Map<String, Boolean> methodMap = new HashMap<String, Boolean>();
			
			for(RoleLimit limit : limits){
				RoleLimitID id = limit.getId();
				Model model = id.getModel();
				Method method = id.getMethod();
				Boolean flag = Boolean.FALSE;
				
				if(limit.getEnable()!=null && limit.getEnable()){
					flag = Boolean.TRUE;
				}
				
				if(model.getTopModel().equals(topModel)){
					String path = getPathFormModelAndMethod(model , method);
					methodMap.put(path, flag);
				}
			}
			
			limitMap.put(name, methodMap);
		}
		
		return limitMap;
	}

	private String getPathFormModelAndMethod(Model model, Method method) {
		StringBuilder path = new StringBuilder();
		String modelPath = model.toPath();
		String methodName = method.getName();
		
		path.append(modelPath+methodName);
		
		return path.toString();
	}

Model 的 toPath 和getTopModel 方法:

public String toPath(){
		StringBuilder path = new StringBuilder();
		List<String> list = new ArrayList<String>();
		Model parent = getParent();
		
		list.add(this.getName());
		
		while(parent != null){
			list.add(parent.getName());
			parent = parent.getParent();
		}
		
		Collections.reverse(list);
		
		for(String str : list){
			path.append(str + IOUtils.DIR_SEPARATOR_UNIX);
		}
		
		return path.toString();
	}

public Model getTopModel(){
		if(isTopModel()){
			return this ;
		}
		else{
			Model parent = getParent();
			
			while(!parent.isTopModel()){
				parent = parent.getParent();
			}
			
			return parent ;
		}
	}

public Boolean isTopModel(){
		return getParent() == null ;
	}

恩,想法很简单的算法都是,就是先把TopModel都取出来,放到set里去重复,然后遍历每个TopModel的权限,做成上面说的那个map结构。

运行有一点小问题,就是空Map,这个在下一篇文章会阐述原因,这里先贴上解决后的结果:

{information={information/contact/search=true, information/produce/search=true, information/contact/modify=true, information/product/detile=true, information/news/create=true, information/company/detile=true, information/company/create=true, information/professional/detile=true,
information/produce/detile=true, information/professional/create=true, information/news/detile=true, information/company/modify=true, information/professional/remove=true, information/company/search=true, information/product/modify=true, information/contact/create=true,
information/product/create=true, information/news/modify=true, information/produce/remove=true, information/product/remove=true, information/professional/modify=true, information/contact/remove=true, information/news/search=true, information/professional/search=true,
information/news/remove=true, information/contact/detile=true, information/produce/create=true, information/product/search=true, information/company/remove=true, information/produce/modify=true}, menu={menu/modify=true, menu/remove=true, menu/detile=true,
menu/create=true, menu/search=true}, recruitment={recruitment/resume/create=true, recruitment/resume/search=true, recruitment/personnel/search=true, recruitment/job/detile=true, recruitment/job/modify=true, recruitment/resume/detile=true, recruitment/personnel/detile=true,
recruitment/resume/remove=true, recruitment/job/create=true, recruitment/personnel/modify=true, recruitment/personnel/create=true, recruitment/resume/modify=true, recruitment/job/remove=true, recruitment/personnel/remove=true, recruitment/job/search=true},
management={management/supervior/detile=true, management/supervior/modify=true, management/supervior/remove=true, management/role/detile=true, management/role/remove=true, management/role/search=true, management/role/modify=true, management/role/create=true,
management/supervior/search=true, management/supervior/create=true}, consult={consult/message/detile=true, consult/message/search=true, consult/reply/search=true, consult/message/create=true, consult/message/remove=true, consult/reply/remove=true, consult/message/modify=true,
consult/reply/detile=true, consult/reply/modify=true, consult/reply/create=true}}

恩,到此,记录完成。

欢迎大家品论,发现目前为止都是浏览,没有品论的。很郁闷。。!

抱歉!评论已关闭.