BOS项目8::权限/角色/用户管理(CRUD),基于数据库实现动态授权,ehcache缓存权限,shiro标签,菜单权限展示

本文主要是介绍BOS项目8::权限/角色/用户管理(CRUD),基于数据库实现动态授权,ehcache缓存权限,shiro标签,菜单权限展示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



目录(?)[-]

  1. 1    权限管理
  2. 2    角色管理
  3. 3    用户管理
  4. 4    修改BOSRealm中的授权方法----基于数据库实现
  5. 5    使用ehcache缓存权限数据
  6. 6    使用shiro提供的标签展示页面元素
  7.   7    系统左侧菜单根据登录人权限展示

内容:

1、权限管理(初始化权限数据、添加、查询)

2、角色管理(添加、查询)

3、用户管理(添加、查询)

4、修改BOSRealm中的授权方法----基于数据库实现

5、使用ehcache缓存权限数据

6、使用shiro提供的标签进行权限控制

7、左侧系统菜单按照登录人权限展示

1.    权限管理

1.1   初始化权限数据到数据库

执行提供的sql文件到数据库


[sql]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. INSERT INTO `auth_function` VALUES ('11''基础档案''jichudangan'nullnull'1''0'null);  
  2. INSERT INTO `auth_function` VALUES ('112''收派标准''standard'null'page_base_standard.action''1''1''11');  
  3. INSERT INTO `auth_function` VALUES ('113''取派员设置''staff'null'page_base_staff.action''1''2''11');  
  4. INSERT INTO `auth_function` VALUES ('114''区域设置''region'null'page_base_region.action''1''3''11');  
  5. INSERT INTO `auth_function` VALUES ('115''管理分区''subarea'null'page_base_subarea.action''1''4''11');  
  6. INSERT INTO `auth_function` VALUES ('116''管理定区/调度排班''decidedzone'null'page_base_decidedzone.action''1''5''11');  
  7. INSERT INTO `auth_function` VALUES ('12''受理''shouli'nullnull'1''1'null);  
  8. INSERT INTO `auth_function` VALUES ('121''业务受理''noticebill'null'page_qupai_noticebill_add.action''1''0''12');  
  9. INSERT INTO `auth_function` VALUES ('122''工作单快速录入''quickworkordermanage'null'page_qupai_quickworkorder.action''1''1''12');  
  10. INSERT INTO `auth_function` VALUES ('124''工作单导入''workordermanageimport'null'page_qupai_workorderimport.action''1''3''12');  
  11. INSERT INTO `auth_function` VALUES ('13''调度''diaodu'nullnull'1''2'null);  
  12. INSERT INTO `auth_function` VALUES ('131''查台转单''changestaff'nullnull'1''0''13');  
  13. INSERT INTO `auth_function` VALUES ('132''人工调度''personalassign'null'page_qupai_diaodu.action''1''1''13');  
  14. INSERT INTO `auth_function` VALUES ('14''物流配送流程管理''zhongzhuan'nullnull'1''3'null);  
  15. INSERT INTO `auth_function` VALUES ('141''启动配送流程''start'null'workOrderManageAction_list.action''1''0''14');  
  16. INSERT INTO `auth_function` VALUES ('142''查看个人任务''personaltask'null'taskAction_findPersonalTask.action''1''1''14');  
  17. INSERT INTO `auth_function` VALUES ('143''查看我的组任务''grouptask'null'taskAction_findGroupTask.action''1''2''14');  

效果


1.2   查询权限数据

权限管理页面:

第一步:修改datagrid的URL地址,访问FunctionAction,获取权限数据展示

第二步:创建FunctionAction,提供pageQuery方法

配置struts.xml

 

1.3   添加权限数据

添加权限页面:

 

第一步:修改combobox的URL地址,加载权限数据,展示到下拉框中

第二步:为“保存”按钮绑定事件

第三步:在Action中提供add方法 

Service代码:

注:

当pid下拉框字段不填写会默认发送空字符串,pid=空字符串引用主键id,主键中没有空这个值,会发生约束错误

org.springframework.dao.InvalidDataAccessApiUsageException:object references an unsaved transient instance - save the transient instancebefore flushing

所以保存前需要先判断一下parentFunction.id是否为空字符串,然后设置为空


[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public void save(Function model) {  
  2.     Function parentFunction = model.getParentFunction();  
  3.     if(parentFunction != null){  
  4.         String id = parentFunction.getId();  
  5.         if(StringUtils.isBlank(id)){  
  6.             model.setParentFunction(null);  
  7.         }  
  8.     }  
  9.     functionDao.save(model);  
  10. }  

第四步:配置struts.xml

  

2.    角色管理

2.1   添加角色

角色添加页面:

 

第一步:在添加角色页面使用ztree展示权限树

 

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. // 授权树初始化  
  2. var setting = {  
  3.     data : {  
  4.         key : {  
  5.             title : "t"  
  6.         },  
  7.         simpleData : {  
  8.             enable : true  
  9.         }  
  10.     },  
  11.     check : {//使用ztree选中效果  
  12.         enable : true,  
  13.     }  
  14. };  
  15.   
  16. $.ajax({  
  17.     url : '${pageContext.request.contextPath}/functionAction_listajax.action',//发送ajax请求加载权限数据  
  18.     type : 'POST',  
  19.     dataType : 'json',  
  20.     success : function(data) {//data就是服务端返回的权限数据  
  21.         //var zNodes = eval("(" + data + ")");  
  22.         //使用权限数据初始化ztree  
  23.         $.fn.zTree.init($("#functionTree"), setting, data);  
  24.     },  
  25.     error : function(msg) {  
  26.         alert('树加载异常!');  
  27.     }  
  28. });  

在权限类中增加一个pId属性来展示ztree的上下级关系效果

注:get方法如果第二个字母大写,那第一个字母必须小写getpId

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1.  * 权限实体  
  2.  * @author zhaoqx  
  3.  *  
  4.  */  
  5. public class Function implements java.io.Serializable {  
  6.   
  7.     // Fields  
  8.   
  9.     private String id;//编号  
  10.     private Function parentFunction;//当前权限对应的上一级权限  
  11.     private String name;//权限名称  
  12.     private String code;//关键字  
  13.     private String description;//描述  
  14.     private String page;//访问URL  
  15.     private String generatemenu;//当前权限是否生成到菜单  1:生成 0:不生成  
  16.     private Integer zindex;//排序  
  17.     private Set children = new HashSet(0);//当前权限对应的多个下级权限  
  18.     private Set roles = new HashSet(0);//当前权限对应的多个角色  
  19.       
  20.     public String getpId() {  
  21.         if(parentFunction == null){  
  22.             return "0";  
  23.         }  
  24.         return parentFunction.getId();  
  25.     }  


第二步:在提交表单之前,使用ztree提供API,动态获取选中的节点

因为ztree的复选框不是checkbox,选中并不会提交,所以要手动获取把id赋值给隐藏域后再提交

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. // 点击保存  
  2. $('#save').click(function(){  
  3.     //location.href='${pageContext.request.contextPath}/page_admin_privilege.action';  
  4.     var v = $("#roleForm").form("validate");  
  5.     if(v){  
  6.         //获得ztree对象  
  7.         var treeObj = $.fn.zTree.getZTreeObj("functionTree");  
  8.         //获得当前ztree对象选中的节点数组  
  9.         var nodes = treeObj.getCheckedNodes(true);//在提交表单之前将选中的checkbox收集  
  10.         //循环数组,获得节点的ID,拼接成字符串使用逗号分隔  
  11.         var array = new Array();  
  12.         for(var i=0;i<nodes.length;i++){  
  13.             array.push(nodes[i].id);  
  14.         }  
  15.         var ids = array.join(",");  
  16.         //为隐藏域赋值  
  17.         $("input[name=funcitonIds]").val(ids);  
  18.         $("#roleForm").submit();  
  19.     }  
  20. });  

 

第三步:创建RoleAction,提供add方法

Service代码:

角色关联权限可以通过通过查询权限id获取持久态权限对象

也可以创建托管态(设置关联id) 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public void save(Role model, String funcitonIds) {  
  2.     roleDao.save(model);//持久对象  
  3.     String[] ids = funcitonIds.split(",");  
  4.     for (String id : ids) {  
  5.         Function function = new Function();  
  6.         function.setId(id);  
  7.         model.getFunctions().add(function);//角色关联权限  
  8.     }  
  9. }  

2.2   查询角色

 

3.    用户管理

3.1   添加用户功能

添加页面:

 

第一步:在添加页面展示角色数据为checkbox

 通过ajax获取角色数据

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <tr><td>选择角色:</td>  
  2.     <td colspan="3" id="roleTD">  
  3.         <script type="text/javascript">  
  4.             $(function(){  
  5.                 //发送ajax请求,获取角色数据,展示位checkbox  
  6.                 var url = "${pageContext.request.contextPath}/roleAction_listajax.action";  
  7.                 $.post(url,{},function(data){  
  8.                     for(var i=0;i<data.length;i++){  
  9.                         var id = data[i].id;  
  10.                         var name = data[i].name;  
  11.                         $("#roleTD").append("<input name='roleIds' value='"+id+"' type='checkbox'>" + name);  
  12.                     }  
  13.                 });  
  14.             });  
  15.         </script>  


第二步:在RoleAction中提供listajax方法,查询所有角色数据,返回json对象

第三步:提交表单

第四步:在UserAction中提供add方法,完成添加用户操作

Service代码:

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. //添加用户  
  2. public void save(User user, String[] roleIds) {  
  3.     String password = user.getPassword();  
  4.     //使用md5加密  
  5.     password = MD5Utils.md5(password);  
  6.     user.setPassword(password);  
  7.     userDao.save(user);//持久对象  
  8.       
  9.     for (String id : roleIds) {  
  10.         Role role = new Role();  
  11.         role.setId(id);  
  12.         //用户关联角色   
  13.         user.getRoles().add(role);  
  14.     }  
  15.       
  16. }  

3.2   用户分页查询


第一步:修改datagrid的URL地址

第二步:在UserAction中提供pageQuery方法进行分页查询

第三步:页面展示时,生日列不能正常显示,在User类中提供一个getBirthdayStr方法

第四步:在页面展示用户对应的角色,在User类中提供方法getRoleNames

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public class User implements java.io.Serializable {  
  2.   
  3.     // Fields  
  4.   
  5.     private String id;  
  6.     private String username;  
  7.     private String password;  
  8.     private Double salary;  
  9.     private Date birthday;  
  10.     private String gender;  
  11.     private String station;  
  12.     private String telephone;  
  13.     private String remark;  
  14.     private Set noticebills = new HashSet(0);  
  15.     private Set<Role> roles = new HashSet(0);//当前用户对应的多个角色  
  16.     //提供生日的字符串属性  
  17.     public String getBirthdayStr(){  
  18.         if(birthday == null){  
  19.             return "";  
  20.         }else{  
  21.             return new SimpleDateFormat("yyyy-MM-dd").format(birthday);  
  22.         }  
  23.     }  
  24.     //提供关联角色的字符串显示属性  
  25.     public String getRoleNames(){  
  26.         String roleNames = "";  
  27.         if(roles != null && roles.size() > 0){  
  28.             for (Role role : roles) {  
  29.                 String name = role.getName();  
  30.                 roleNames += name + " ";  
  31.             }  
  32.         }  
  33.         return roleNames;  
  34.     }  


4.    修改BOSRealm中的授权方法----基于数据库实现

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 自定义realm,实现认证和授权 
  3.  *  
  4.  * @author zhaoqx 
  5.  *  
  6.  */  
  7. public class BOSRealm extends AuthorizingRealm {  
  8.     // 注入dao  
  9.     @Resource  
  10.     private IUserDao userDao;  
  11.     @Resource  
  12.     private IFunctionDao functionDao;  
  13.   
  14.     // 认证方法  
  15.     protected AuthenticationInfo doGetAuthenticationInfo(  
  16.             AuthenticationToken token) throws AuthenticationException {  
  17.         System.out.println("认证方法。。。。");  
  18.         UsernamePasswordToken pwdToken = (UsernamePasswordToken) token;  
  19.         String username = pwdToken.getUsername();  
  20.         // 根据用户名查询密码,由安全管理器负责比对查询出的数据库中的密码和页面输入的密码是否一致  
  21.         User user = userDao.findUserByUsername(username);  
  22.         if(user == null){  
  23.             return null;  
  24.         }  
  25.         String dbPassword = user.getPassword();  
  26.         //参数一:  
  27.         AuthenticationInfo info = new SimpleAuthenticationInfo(user,  
  28.                 dbPassword, this.getClass().getSimpleName());  
  29.         return info;  
  30.     }  
  31.   
  32.     // 授权方法  
  33.     protected AuthorizationInfo doGetAuthorizationInfo(  
  34.             PrincipalCollection principals) {  
  35.           
  36.         User user = (User) principals.getPrimaryPrincipal();  
  37.         System.out.println(user);  
  38.           
  39.         Subject subject = SecurityUtils.getSubject();  
  40.         User user2 = (User) subject.getPrincipal();  
  41.           
  42.         //User user3 = BOSContext.getLoginUser();  
  43.           
  44.         //为所用的用户授予staff权限  
  45.         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  46.         List<Function> list = null;//  
  47.         //根据当前登录用户,查询用户的角色,根据角色对应获得权限,将权限添加到信息对象中  
  48.         if(user.getUsername().equals("admin")){  
  49.             //如果是超级管理员,授予所有权限  
  50.             list = functionDao.findAll();  
  51.         }else{  
  52.             //普通用户,根据用户查询对应的权限  
  53.             list = functionDao.findFunctionsByUserId(user.getId());  
  54.         }  
  55.           
  56.         for (Function function : list) {  
  57.             //权限的关键字  
  58.             String code = function.getCode();  
  59.             info.addStringPermission(code);  
  60.         }  
  61.           
  62.         return info;  
  63.     }  
  64.   
  65. }  


FunctionDao中:

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. @Repository  
  2. public class FunctionDaoImpl extends BaseDaoImpl<Function> implements IFunctionDao{  
  3.   
  4.     public List<Function> findFunctionsByUserId(String userid) {  
  5.         String hql = "select f from Function f left outer join " +  
  6.                 "f.roles r left outer join r.users u where u.id = ?";  
  7.         return this.getHibernateTemplate().find(hql,userid);  
  8.     }  

 

 

5.    使用ehcache缓存权限数据

第一步:将ehcache的jar导入到bos项目中

com.springsource.net.sf.ehcache-1.6.2.jar

第二步:在项目config目录下提供ehcache的配置文件(jar包中的配置文件)

ehcache.xml

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  
  2.   
  3.      
  4.     <diskStore path="java.io.tmpdir"/>  
  5.   
  6.       
  7.     <defaultCache  
  8.             maxElementsInMemory="10000"  
  9.             eternal="false"  
  10.             timeToIdleSeconds="120"  
  11.             timeToLiveSeconds="120"  
  12.             overflowToDisk="true"  
  13.             maxElementsOnDisk="10000000"  
  14.             diskPersistent="false"  
  15.             diskExpiryThreadIntervalSeconds="120"  
  16.             memoryStoreEvictionPolicy="LRU"  
  17.             />  
  18. </ehcache>  

第三步:在spring配置文件中配置一个缓存管理器

 

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 定义安全管理器 -->  
  2. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  3.     <!-- 注入realm -->  
  4.     <property name="realm" ref="bosRealm"></property>  
  5.     <!-- 注入缓存管理器 -->  
  6.     <property name="cacheManager" ref="cacheManager"></property>  
  7. </bean>  
  8.   
  9. <!-- 注册一个缓存管理器 -->  
  10. <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">  
  11.     <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>  
  12. </bean>  


6.    使用shiro提供的标签展示页面元素


第一步:引入shiro标签库

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>    

第二步:在需要进行权限控制的元素上使用标签

 

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <shiro:hasPermission name="staff">  
  2. {  
  3.     id : 'button-add',  
  4.     text : '增加',  
  5.     iconCls : 'icon-add',  
  6.     handler : doAdd  
  7. },  
  8. </shiro:hasPermission>  

其他shiro标签


 
7.    系统左侧菜单根据登录人权限展示

第一步:修改/WEB-INF/pages/common/index.jsp的ajax方法提交地址

第二步:在UserAction中提供findMenu,根据登录人查询对应的菜单数据

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 根据登录人查询对应的权限菜单数据 
  3.  */  
  4. public String findMenu(){  
  5.     User user = BOSContext.getLoginUser();  
  6.     List<Function> list = null;  
  7.     if(user.getUsername().equals("admin")){  
  8.         //超级管理员,加载所有的菜单数据  
  9.         list = functionService.findAllMenu();  
  10.     }else{  
  11.         //根据用户ID查询菜单数据  
  12.         list = functionService.findMenuByUserId(user.getId());  
  13.     }  
  14.       
  15.     String[] excludes = new String[]{"parentFunction","children","roles"};  
  16.     this.writeListBean2Json(list, excludes );  
  17.     return NONE;  
  18. }  

FunctionDao中:


角色重复造成权限菜单重复

在查询时需要排除重复的权限

hql 语句加上distinct

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public List<Function> findAllMenu() {  
  2.     String hql = "from Function f where f.generatemenu = '1' order by f.zindex";  
  3.     return this.getHibernateTemplate().find(hql);  
  4. }  
  5.   
  6. public List<Function> findMenuByUserId(String id) {  
  7.     String hql = "select distinct f from Function f left outer join " +  
  8.             "f.roles r left outer join r.users u where u.id = ? and " +  
  9.             "f.generatemenu = '1' order by f.zindex";  
  10.     return this.getHibernateTemplate().find(hql,id);  
  11. }  


 

目录(?)[-]

  1. 1    权限管理
  2. 2    角色管理
  3. 3    用户管理
  4. 4    修改BOSRealm中的授权方法----基于数据库实现
  5. 5    使用ehcache缓存权限数据
  6. 6    使用shiro提供的标签展示页面元素
  7.   7    系统左侧菜单根据登录人权限展示

内容:

1、权限管理(初始化权限数据、添加、查询)

2、角色管理(添加、查询)

3、用户管理(添加、查询)

4、修改BOSRealm中的授权方法----基于数据库实现

5、使用ehcache缓存权限数据

6、使用shiro提供的标签进行权限控制

7、左侧系统菜单按照登录人权限展示

1.    权限管理

1.1   初始化权限数据到数据库

执行提供的sql文件到数据库


[sql]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. INSERT INTO `auth_function` VALUES ('11''基础档案''jichudangan'nullnull'1''0'null);  
  2. INSERT INTO `auth_function` VALUES ('112''收派标准''standard'null'page_base_standard.action''1''1''11');  
  3. INSERT INTO `auth_function` VALUES ('113''取派员设置''staff'null'page_base_staff.action''1''2''11');  
  4. INSERT INTO `auth_function` VALUES ('114''区域设置''region'null'page_base_region.action''1''3''11');  
  5. INSERT INTO `auth_function` VALUES ('115''管理分区''subarea'null'page_base_subarea.action''1''4''11');  
  6. INSERT INTO `auth_function` VALUES ('116''管理定区/调度排班''decidedzone'null'page_base_decidedzone.action''1''5''11');  
  7. INSERT INTO `auth_function` VALUES ('12''受理''shouli'nullnull'1''1'null);  
  8. INSERT INTO `auth_function` VALUES ('121''业务受理''noticebill'null'page_qupai_noticebill_add.action''1''0''12');  
  9. INSERT INTO `auth_function` VALUES ('122''工作单快速录入''quickworkordermanage'null'page_qupai_quickworkorder.action''1''1''12');  
  10. INSERT INTO `auth_function` VALUES ('124''工作单导入''workordermanageimport'null'page_qupai_workorderimport.action''1''3''12');  
  11. INSERT INTO `auth_function` VALUES ('13''调度''diaodu'nullnull'1''2'null);  
  12. INSERT INTO `auth_function` VALUES ('131''查台转单''changestaff'nullnull'1''0''13');  
  13. INSERT INTO `auth_function` VALUES ('132''人工调度''personalassign'null'page_qupai_diaodu.action''1''1''13');  
  14. INSERT INTO `auth_function` VALUES ('14''物流配送流程管理''zhongzhuan'nullnull'1''3'null);  
  15. INSERT INTO `auth_function` VALUES ('141''启动配送流程''start'null'workOrderManageAction_list.action''1''0''14');  
  16. INSERT INTO `auth_function` VALUES ('142''查看个人任务''personaltask'null'taskAction_findPersonalTask.action''1''1''14');  
  17. INSERT INTO `auth_function` VALUES ('143''查看我的组任务''grouptask'null'taskAction_findGroupTask.action''1''2''14');  

效果


1.2   查询权限数据

权限管理页面:

第一步:修改datagrid的URL地址,访问FunctionAction,获取权限数据展示

第二步:创建FunctionAction,提供pageQuery方法

配置struts.xml

 

1.3   添加权限数据

添加权限页面:

 

第一步:修改combobox的URL地址,加载权限数据,展示到下拉框中

第二步:为“保存”按钮绑定事件

第三步:在Action中提供add方法 

Service代码:

注:

当pid下拉框字段不填写会默认发送空字符串,pid=空字符串引用主键id,主键中没有空这个值,会发生约束错误

org.springframework.dao.InvalidDataAccessApiUsageException:object references an unsaved transient instance - save the transient instancebefore flushing

所以保存前需要先判断一下parentFunction.id是否为空字符串,然后设置为空


[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public void save(Function model) {  
  2.     Function parentFunction = model.getParentFunction();  
  3.     if(parentFunction != null){  
  4.         String id = parentFunction.getId();  
  5.         if(StringUtils.isBlank(id)){  
  6.             model.setParentFunction(null);  
  7.         }  
  8.     }  
  9.     functionDao.save(model);  
  10. }  

第四步:配置struts.xml

  

2.    角色管理

2.1   添加角色

角色添加页面:

 

第一步:在添加角色页面使用ztree展示权限树

 

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. // 授权树初始化  
  2. var setting = {  
  3.     data : {  
  4.         key : {  
  5.             title : "t"  
  6.         },  
  7.         simpleData : {  
  8.             enable : true  
  9.         }  
  10.     },  
  11.     check : {//使用ztree选中效果  
  12.         enable : true,  
  13.     }  
  14. };  
  15.   
  16. $.ajax({  
  17.     url : '${pageContext.request.contextPath}/functionAction_listajax.action',//发送ajax请求加载权限数据  
  18.     type : 'POST',  
  19.     dataType : 'json',  
  20.     success : function(data) {//data就是服务端返回的权限数据  
  21.         //var zNodes = eval("(" + data + ")");  
  22.         //使用权限数据初始化ztree  
  23.         $.fn.zTree.init($("#functionTree"), setting, data);  
  24.     },  
  25.     error : function(msg) {  
  26.         alert('树加载异常!');  
  27.     }  
  28. });  

在权限类中增加一个pId属性来展示ztree的上下级关系效果

注:get方法如果第二个字母大写,那第一个字母必须小写getpId

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1.  * 权限实体  
  2.  * @author zhaoqx  
  3.  *  
  4.  */  
  5. public class Function implements java.io.Serializable {  
  6.   
  7.     // Fields  
  8.   
  9.     private String id;//编号  
  10.     private Function parentFunction;//当前权限对应的上一级权限  
  11.     private String name;//权限名称  
  12.     private String code;//关键字  
  13.     private String description;//描述  
  14.     private String page;//访问URL  
  15.     private String generatemenu;//当前权限是否生成到菜单  1:生成 0:不生成  
  16.     private Integer zindex;//排序  
  17.     private Set children = new HashSet(0);//当前权限对应的多个下级权限  
  18.     private Set roles = new HashSet(0);//当前权限对应的多个角色  
  19.       
  20.     public String getpId() {  
  21.         if(parentFunction == null){  
  22.             return "0";  
  23.         }  
  24.         return parentFunction.getId();  
  25.     }  


第二步:在提交表单之前,使用ztree提供API,动态获取选中的节点

因为ztree的复选框不是checkbox,选中并不会提交,所以要手动获取把id赋值给隐藏域后再提交

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. // 点击保存  
  2. $('#save').click(function(){  
  3.     //location.href='${pageContext.request.contextPath}/page_admin_privilege.action';  
  4.     var v = $("#roleForm").form("validate");  
  5.     if(v){  
  6.         //获得ztree对象  
  7.         var treeObj = $.fn.zTree.getZTreeObj("functionTree");  
  8.         //获得当前ztree对象选中的节点数组  
  9.         var nodes = treeObj.getCheckedNodes(true);//在提交表单之前将选中的checkbox收集  
  10.         //循环数组,获得节点的ID,拼接成字符串使用逗号分隔  
  11.         var array = new Array();  
  12.         for(var i=0;i<nodes.length;i++){  
  13.             array.push(nodes[i].id);  
  14.         }  
  15.         var ids = array.join(",");  
  16.         //为隐藏域赋值  
  17.         $("input[name=funcitonIds]").val(ids);  
  18.         $("#roleForm").submit();  
  19.     }  
  20. });  

 

第三步:创建RoleAction,提供add方法

Service代码:

角色关联权限可以通过通过查询权限id获取持久态权限对象

也可以创建托管态(设置关联id) 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public void save(Role model, String funcitonIds) {  
  2.     roleDao.save(model);//持久对象  
  3.     String[] ids = funcitonIds.split(",");  
  4.     for (String id : ids) {  
  5.         Function function = new Function();  
  6.         function.setId(id);  
  7.         model.getFunctions().add(function);//角色关联权限  
  8.     }  
  9. }  

2.2   查询角色

 

3.    用户管理

3.1   添加用户功能

添加页面:

 

第一步:在添加页面展示角色数据为checkbox

 通过ajax获取角色数据

[javascript]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <tr><td>选择角色:</td>  
  2.     <td colspan="3" id="roleTD">  
  3.         <script type="text/javascript">  
  4.             $(function(){  
  5.                 //发送ajax请求,获取角色数据,展示位checkbox  
  6.                 var url = "${pageContext.request.contextPath}/roleAction_listajax.action";  
  7.                 $.post(url,{},function(data){  
  8.                     for(var i=0;i<data.length;i++){  
  9.                         var id = data[i].id;  
  10.                         var name = data[i].name;  
  11.                         $("#roleTD").append("<input name='roleIds' value='"+id+"' type='checkbox'>" + name);  
  12.                     }  
  13.                 });  
  14.             });  
  15.         </script>  


第二步:在RoleAction中提供listajax方法,查询所有角色数据,返回json对象

第三步:提交表单

第四步:在UserAction中提供add方法,完成添加用户操作

Service代码:

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. //添加用户  
  2. public void save(User user, String[] roleIds) {  
  3.     String password = user.getPassword();  
  4.     //使用md5加密  
  5.     password = MD5Utils.md5(password);  
  6.     user.setPassword(password);  
  7.     userDao.save(user);//持久对象  
  8.       
  9.     for (String id : roleIds) {  
  10.         Role role = new Role();  
  11.         role.setId(id);  
  12.         //用户关联角色   
  13.         user.getRoles().add(role);  
  14.     }  
  15.       
  16. }  

3.2   用户分页查询


第一步:修改datagrid的URL地址

第二步:在UserAction中提供pageQuery方法进行分页查询

第三步:页面展示时,生日列不能正常显示,在User类中提供一个getBirthdayStr方法

第四步:在页面展示用户对应的角色,在User类中提供方法getRoleNames

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public class User implements java.io.Serializable {  
  2.   
  3.     // Fields  
  4.   
  5.     private String id;  
  6.     private String username;  
  7.     private String password;  
  8.     private Double salary;  
  9.     private Date birthday;  
  10.     private String gender;  
  11.     private String station;  
  12.     private String telephone;  
  13.     private String remark;  
  14.     private Set noticebills = new HashSet(0);  
  15.     private Set<Role> roles = new HashSet(0);//当前用户对应的多个角色  
  16.     //提供生日的字符串属性  
  17.     public String getBirthdayStr(){  
  18.         if(birthday == null){  
  19.             return "";  
  20.         }else{  
  21.             return new SimpleDateFormat("yyyy-MM-dd").format(birthday);  
  22.         }  
  23.     }  
  24.     //提供关联角色的字符串显示属性  
  25.     public String getRoleNames(){  
  26.         String roleNames = "";  
  27.         if(roles != null && roles.size() > 0){  
  28.             for (Role role : roles) {  
  29.                 String name = role.getName();  
  30.                 roleNames += name + " ";  
  31.             }  
  32.         }  
  33.         return roleNames;  
  34.     }  


4.    修改BOSRealm中的授权方法----基于数据库实现

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 自定义realm,实现认证和授权 
  3.  *  
  4.  * @author zhaoqx 
  5.  *  
  6.  */  
  7. public class BOSRealm extends AuthorizingRealm {  
  8.     // 注入dao  
  9.     @Resource  
  10.     private IUserDao userDao;  
  11.     @Resource  
  12.     private IFunctionDao functionDao;  
  13.   
  14.     // 认证方法  
  15.     protected AuthenticationInfo doGetAuthenticationInfo(  
  16.             AuthenticationToken token) throws AuthenticationException {  
  17.         System.out.println("认证方法。。。。");  
  18.         UsernamePasswordToken pwdToken = (UsernamePasswordToken) token;  
  19.         String username = pwdToken.getUsername();  
  20.         // 根据用户名查询密码,由安全管理器负责比对查询出的数据库中的密码和页面输入的密码是否一致  
  21.         User user = userDao.findUserByUsername(username);  
  22.         if(user == null){  
  23.             return null;  
  24.         }  
  25.         String dbPassword = user.getPassword();  
  26.         //参数一:  
  27.         AuthenticationInfo info = new SimpleAuthenticationInfo(user,  
  28.                 dbPassword, this.getClass().getSimpleName());  
  29.         return info;  
  30.     }  
  31.   
  32.     // 授权方法  
  33.     protected AuthorizationInfo doGetAuthorizationInfo(  
  34.             PrincipalCollection principals) {  
  35.           
  36.         User user = (User) principals.getPrimaryPrincipal();  
  37.         System.out.println(user);  
  38.           
  39.         Subject subject = SecurityUtils.getSubject();  
  40.         User user2 = (User) subject.getPrincipal();  
  41.           
  42.         //User user3 = BOSContext.getLoginUser();  
  43.           
  44.         //为所用的用户授予staff权限  
  45.         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  46.         List<Function> list = null;//  
  47.         //根据当前登录用户,查询用户的角色,根据角色对应获得权限,将权限添加到信息对象中  
  48.         if(user.getUsername().equals("admin")){  
  49.             //如果是超级管理员,授予所有权限  
  50.             list = functionDao.findAll();  
  51.         }else{  
  52.             //普通用户,根据用户查询对应的权限  
  53.             list = functionDao.findFunctionsByUserId(user.getId());  
  54.         }  
  55.           
  56.         for (Function function : list) {  
  57.             //权限的关键字  
  58.             String code = function.getCode();  
  59.             info.addStringPermission(code);  
  60.         }  
  61.           
  62.         return info;  
  63.     }  
  64.   
  65. }  


FunctionDao中:

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. @Repository  
  2. public class FunctionDaoImpl extends BaseDaoImpl<Function> implements IFunctionDao{  
  3.   
  4.     public List<Function> findFunctionsByUserId(String userid) {  
  5.         String hql = "select f from Function f left outer join " +  
  6.                 "f.roles r left outer join r.users u where u.id = ?";  
  7.         return this.getHibernateTemplate().find(hql,userid);  
  8.     }  

 

 

5.    使用ehcache缓存权限数据

第一步:将ehcache的jar导入到bos项目中

com.springsource.net.sf.ehcache-1.6.2.jar

第二步:在项目config目录下提供ehcache的配置文件(jar包中的配置文件)

ehcache.xml

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  
  2.   
  3.      
  4.     <diskStore path="java.io.tmpdir"/>  
  5.   
  6.       
  7.     <defaultCache  
  8.             maxElementsInMemory="10000"  
  9.             eternal="false"  
  10.             timeToIdleSeconds="120"  
  11.             timeToLiveSeconds="120"  
  12.             overflowToDisk="true"  
  13.             maxElementsOnDisk="10000000"  
  14.             diskPersistent="false"  
  15.             diskExpiryThreadIntervalSeconds="120"  
  16.             memoryStoreEvictionPolicy="LRU"  
  17.             />  
  18. </ehcache>  

第三步:在spring配置文件中配置一个缓存管理器

 

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 定义安全管理器 -->  
  2. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  3.     <!-- 注入realm -->  
  4.     <property name="realm" ref="bosRealm"></property>  
  5.     <!-- 注入缓存管理器 -->  
  6.     <property name="cacheManager" ref="cacheManager"></property>  
  7. </bean>  
  8.   
  9. <!-- 注册一个缓存管理器 -->  
  10. <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">  
  11.     <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>  
  12. </bean>  


6.    使用shiro提供的标签展示页面元素


第一步:引入shiro标签库

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>    

第二步:在需要进行权限控制的元素上使用标签

 

[html]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <shiro:hasPermission name="staff">  
  2. {  
  3.     id : 'button-add',  
  4.     text : '增加',  
  5.     iconCls : 'icon-add',  
  6.     handler : doAdd  
  7. },  
  8. </shiro:hasPermission>  

其他shiro标签


 
7.    系统左侧菜单根据登录人权限展示

第一步:修改/WEB-INF/pages/common/index.jsp的ajax方法提交地址

第二步:在UserAction中提供findMenu,根据登录人查询对应的菜单数据

 

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 根据登录人查询对应的权限菜单数据 
  3.  */  
  4. public String findMenu(){  
  5.     User user = BOSContext.getLoginUser();  
  6.     List<Function> list = null;  
  7.     if(user.getUsername().equals("admin")){  
  8.         //超级管理员,加载所有的菜单数据  
  9.         list = functionService.findAllMenu();  
  10.     }else{  
  11.         //根据用户ID查询菜单数据  
  12.         list = functionService.findMenuByUserId(user.getId());  
  13.     }  
  14.       
  15.     String[] excludes = new String[]{"parentFunction","children","roles"};  
  16.     this.writeListBean2Json(list, excludes );  
  17.     return NONE;  
  18. }  

FunctionDao中:


角色重复造成权限菜单重复

在查询时需要排除重复的权限

hql 语句加上distinct

[java]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. public List<Function> findAllMenu() {  
  2.     String hql = "from Function f where f.generatemenu = '1' order by f.zindex";  
  3.     return this.getHibernateTemplate().find(hql);  
  4. }  
  5.   
  6. public List<Function> findMenuByUserId(String id) {  
  7.     String hql = "select distinct f from Function f left outer join " +  
  8.             "f.roles r left outer join r.users u where u.id = ? and " +  
  9.             "f.generatemenu = '1' order by f.zindex";  
  10.     return this.getHibernateTemplate().find(hql,id);  
  11. }  


 

这篇关于BOS项目8::权限/角色/用户管理(CRUD),基于数据库实现动态授权,ehcache缓存权限,shiro标签,菜单权限展示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/369139

相关文章

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具