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

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表