第1章 权限管理原理知识1.1 什么是权限管理1.2 用户认证1.2.1 概念1.2.1 用户认证流程1.2.2 关键对象1.3 用户授权1.3.1 概念1.3.2 授权流程1.3.3 关键对象1.3.4 分配权限1.3.5 权限模型1.3.6 权限控制1.3.6.1 基于角色的访问控制1.3.6.2 基于资源的访问控制第2章 权限管理解决方案2.1 什么是粗粒度和细粒度权限2.2 如何实现粗粒度和细粒度权限管理2.3 基于url拦截方式实现2.4 使用权限管理框架实现第3章.基于url的权限管理3.1 基于url权限管理流程3.2 搭建环境3.2.1 数据库3.2.2 技术 架构3.2.3 系统登录3.2.3.1 用户的身份信息3.2.3.1 mapper3.2.3.2 service3.2.3.2 controller。
credential:
凭证信息,可以是密码、证书、指纹。
总结:
主体在进行身份认证时需要提供身份信息和凭证信息。
用户授权,简单理解为访问控制
,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限方可访问。
授权的过程理解为: who 对 what 进行how操作。
who: 主体即subject,subject在认证通过后系统进行访问控制。
what: 资源,subject 必须就别资源的访问权限才可访问该资源。比如:系统用户列表页面、商品修改菜单、商品id为001的商品信息。
how: 权限/许可,针对资源的权限或许可,subject具有permission访问资源,如何访问/操作需要定义permission,权限比如:用户添加、用户修改、商品删除。
1.3.4 分配权限用户需要分配相应的权限才可访问相应的资源。权限是对于资源的操作许可。通常给用户分配资源权限需要将权限信息持久化,比如存储在关系数据库里。把用户信息、权限管理、用户分配的权限信息写到数据库中。
1.3.5 权限模型主体
资源
权限
角色
角色和权限关系
主体和角色关系
合并为
权限1.3.6.1 基于角色的访问控制
RBAC,基于角色的访问控制比如:系统角色包括:部门经理、总经理…){3 //系统资源的内容4 //用户报表查看5}
问题:
角色是针对人划分的,人作为用户在系统中是属于活动的内容,如果说该角色可以访问的资源出现变更,需要修改你的代码。比如:部门经理和总经理都可以查看进行报表的查看,代码改为:
1if||user.hasRole){2 //系统资源的内容3 //用户报表查看4}
基于角色的访问控制是不利于系统维护的。
1.3.6.2 基于资源的访问控制RBAC,基于资源的访问控制资源在系统中是不变的,比如资源有:类中的方法,页面中的按钮。对资源的范文需要具有permission权限,代码可以写为;
1if){2 //系统资源的内容3 //用户报表查看4}
上边的方法可以解决用户角色变更不用修改上边权限控制的代码。如果需要变更权限只需要在分配权限模块去操作,给部门经理或总经理增或删除权限。建议使用基于资源的访问控制实现权限管理。
第2章 权限管理解决方案2.1 什么是粗粒度和细粒度权限粗粒度权限管理
,对资源类型的权限管理。资源类型比如:菜单、URL连接、用户添加页面、用户信息、类方法、页面中的按钮。粗粒度权限管理比如:超级管理员可以访问用户添加 页面、用户信息等全部页面。部门管理员可以访问用户信息页面包括页面中的所有按钮细粒度权限管理
,对资源实例的权限管理。资源实例就是资源类型的具体化,比如:用户id为001的修改连接,1110班的用户信息、行政部的员工。细粒度权限管理就是数据级别的权限管理。细粒度权限管理比如: 部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单。
如何实现粗粒度权限管理
?粗粒度权限管理比较容易将权限管理的代码抽取出来在系统架构级别统一处理。比如:通过springmvc拦截器实现授权。如何实现细粒度权限管理
?建议细粒度权限管理在业务层去控制。比如:部门经理只查询本部门员工信息,在service接口提供一个部门id的查询,controller中根据当前用户的信息得到该用户属于哪个部门,调用service时将部门id传入service,实现用户只查询本部门的员工。
基于url拦截的方式实现在实际开发中比较常用的一种方式。对于web系统,通过filter过滤器实现url拦截,也可以springmvc的拦截器实现基于 url的拦截
2.4 使用权限管理框架实现对于粗粒度权限管理,建立使用优秀权限管理框架来实现,节省开发时间,提高开发效率,shiro就是一个优秀权限管理框架。
第3章.基于url的权限管理3.1 基于url权限管理流程3.2 搭建环境3.2.1 数据库需要创建:用户表、角色表、权限表、用户角色表、角色权限表
1CREATE TABLE `sys_user` NOT NULL COMMENT "主键", 3 `usercode` varchar NOT NULL COMMENT "账号", 4 `username` varchar NOT NULL COMMENT "姓名", 5 `password` varchar NOT NULL COMMENT "密码", 6 `salt` varchar DEFAULT NULL COMMENT "盐", 7 `locked` char DEFAULT NULL COMMENT "账号是否锁定,1:锁定,0未锁定", 8 PRIMARY KEY 9) ENGINE=InnoDB DEFAULT CHARSET=utf8;10CREATE TABLE `sys_role` NOT NULL,12 `name` varchar NOT NULL,13 `available` char DEFAULT NULL COMMENT "是否可用,1:可用,0不可用",14 PRIMARY KEY 15) ENGINE=InnoDB DEFAULT CHARSET=utf8;16CREATE TABLE `sys_user_role` NOT NULL,18 `sys_user_id` varchar NOT NULL,19 `sys_role_id` varchar NOT NULL,20 PRIMARY KEY 21) ENGINE=InnoDB DEFAULT CHARSET=utf8;22CREATE TABLE `sys_permission` NOT NULL COMMENT "主键",24 `name` varchar NOT NULL COMMENT "资源名称",25 `type` varchar NOT NULL COMMENT "资源类型:menu,button,",26 `url` varchar DEFAULT NULL COMMENT "访问url地址",27 `percode` varchar DEFAULT NULL COMMENT "权限代码字符串",28 `parentid` bigint DEFAULT NULL COMMENT "父结点id",29 `parentids` varchar DEFAULT NULL COMMENT "父结点id列表串",30 `sortstring` varchar DEFAULT NULL COMMENT "排序号",31 `available` char DEFAULT NULL COMMENT "是否可用,1:可用,0不可用",32 PRIMARY KEY 33) ENGINE=InnoDB DEFAULT CHARSET=utf8;34CREATE TABLE `sys_role_permission` NOT NULL,36 `sys_role_id` varchar NOT NULL COMMENT "角色id",37 `sys_permission_id` varchar NOT NULL COMMENT "权限id",38 PRIMARY KEY 39) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1insert into `sys_permission` values ,,,,,,,,,;2/*Data for the table `sys_role` */3insert into `sys_role` values ,;4/*Data for the table `sys_role_permission` */5insert into `sys_role_permission` values ,,,,,;6/*Data for the table `sys_user` */7insert into `sys_user` values ,;8/*Data for the table `sys_user_role` */9insert into `sys_user_role` values ,;
3.2.2 技术 架构
springmvc + mybatis + jquery easyui
3.2.3 系统登录系统登录相当于用户认证,用户登录成功,要在session中记录用户的身份信息。操作流程:1.用户进入登录页面2.输入用户名和密码进行登录3.进行用户名和密码校验4.如果校验通过,在session中记录用户信息
3.2.3.1 用户的身份信息 1/** 2 * 用户身份信息,存入session 由于tomcat将session会序列化在本地硬盘上,所以使用Serializable接口 3 * 4 */ 5public class ActiveUser implements java.io.Serializable { 6 private String userid;//用户id 7 private String usercode;// 用户账号 8 private String username;// 用户名称 9 private List
3.2.3.1 mapper
使用逆向工程生成的mapper,根据用户账户查询用户信息。
3.2.3.2 service接口功能:根据用户的身份和密码 进行认证,如果认证通过,返回用户身份信息认证过程:
根据用户身份查询数据库,如果查询不到用户不存在
对输入的密码 和数据库密码 进行比对,如果一致,认证通过
1@Override 2 public ActiveUser authenticat 3 throws Exception { 4 /** 5 认证过程: 6 根据用户身份查询数据库,如果查询不到用户不存在 7 对输入的密码 和数据库密码 进行比对,如果一致,认证通过 8 */ 9 //根据用户账号查询数据库10 SysUser sysUser = this.findSysUserByUserCode;11 if{12 //抛出异常13 throw new CustomException;14 }15 //数据库密码 16 String password_db = sysUser.getPassword;17 //对输入的密码 和数据库密码 进行比对,如果一致,认证通过18 //对页面输入的密码 进行md5加密 19 String password_input_md5 = new MD5.getMD5ofStr;20 if){21 //抛出异常22 throw new CustomException;23 }24 //得到用户id25 String userid = sysUser.getId;26 //根据用户id查询菜单 27 List menus =this.findMenuListByUserId;28 //根据用户id查询权限url29 List permissions = this.findPermissionListByUserId;30 //认证通过,返回用户身份信息31 ActiveUser activeUser = new ActiveUser;32 activeUser.setUserid);33 activeUser.setUsercode;34 activeUser.setUsername);//用户名称35 //放入权限范围的菜单和url36 activeUser.setMenus;37 activeUser.setPermissions;38 return activeUser;39 }
3.2.3.2 controllerthrows Exception{ 2 //校验验证码,防止恶性攻击 3 //从session获取正确验证码 4 String validateCode = session.getAttribute; 5 //输入的验证和session中的验证进行对比 6 if){ 7 //抛出异常 8 throw new CustomException; 9 }10 //调用service校验用户账号和密码的正确性11 ActiveUser activeUser = sysService.authenticat;12 //如果service校验通过,将用户身份记录到session13 session.setAttribute;14 //重定向到商品查询页面15 return "redirect:/first.action";16 }3.2.4 用户认证拦截器3.2.4.1 编写认证拦截器 1//用于用户认证校验、用户权限校验 2 @Override 3 public boolean preHandle throws Exception { 5 //得到请求的url 6 String url = request.getRequestURI; 7 //判断是否是公开 地址 8 //实际开发中需要公开 地址配置在配置文件中 9 //从配置中取逆名访问url10 List open_urls = ResourcesUtil.gekeyList;11 //遍历公开 地址,如果是公开 地址则放行12 for{13 if>=0){14 //如果是公开 地址则放行15 return true;16 }17 }18 //判断用户身份在session中是否存在19 HttpSession session = request.getSession;20 ActiveUser activeUser = session.getAttribute;21 //如果用户身份在session中存在放行22 if{23 return true;24 }25 //执行到这里拦截,跳转到登陆页面,用户进行身份认证26 request.getRequestDispatcher.forward;27 //如果返回false表示拦截不继续执行handler,如果返回true表示放行28 return false;29 }
3.2.4.2 配置拦截器1 2
3.2.5 授权3.2.5.1 commonURL.properties
在此配置文件配置公共访问地址,共用访问地址只要 通过用户认证,不需要对公共访问地址分配 权限即可访问。
3.2.5.2 获取用户权限范围的菜单思路:在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的菜单,将菜单的集合存储在session 中。
1public class ActiveUser implements java.io.Serializable {2 private String userid;//用户id3 private String usercode;// 用户账号4 private String username;// 用户名称5 private List menus;// 菜单6 private List permissions;// 权限7 // set get方法省略8}
mapper接口:根据用户id查询用户权限的菜单
1 2
service接口:根据用户id查询用户权限的菜单
1public List findMenuListByUserId2 throws Exception {3 return sysPermissionMapperCustom.findMenuListByUserId;4 }
3.2.5.3 获取用户权限范围的url思路:在用户认证时,认证通过,根据用户id从数据库获取权限分为的url,将url的集合存储在session 中。mapper接口:根据用户id查询用户权限的url
1 2
service接口:根据用户id查询权限的url
1@Override2public List findPermissionListByUserId3 throws Exception {4 return sysPermissionMapperCustom.findPermissionListByUserId;5}
3.2.5.4 用户认证通过取出菜单和url放入session 1 //得到用户id 2 String userid = sysUser.getId; 3 //根据用户id查询菜单 4 List
3.2.5.6 菜单动态显示 1
3.2.5.7 授权拦截器
1//在执行handler之前来执行的 2 //用于用户认证校验、用户权限校验 3 @Override 4 public boolean preHandle throws Exception { 6 //得到请求的url 7 String url = request.getRequestURI; 8 //判断是否是公开 地址 9 //实际开发中需要公开 地址配置在配置文件中10 //从配置中取逆名访问url11 List
3.2.5.8 配置授权拦截器 1 2
总结
使用基于url拦截的权限管理方式,实现起来比较简单,不依赖于框架,使用Web提供filter就可以实现。问题
:需要将所有的url全部配置起来,有些繁琐,不易维护,url和权限表示方式不规范。