访问控制策略
了解一下RBAC
访问控制策略一般有以下几种方式:
(1)自由型访问控制:用户|对象来决定访问权限。信息的所有者来设定谁有权限来访问信息以及操作类型(读,写,执行...)是一种基于身份的访问控制。例如UNIX权限管理。(2)强制性访问控制:系统来决定访问权限。安全属性是强制型的规定,它由安全管理员或操作系统根据限定的规则确定的,是一种规则的访问控制
(3)基于角色的访问控制:角色决定访问权限。用组织角色来同意或拒绝访问。比MAC,DAC更灵活,适合作为大多数公司的安全策略,但对一些机密性高的政府系统不适用。——————————————————[本次实现]
(4)规则驱动的基于角色的访问控制:提供了一种基于约束的访问控制,用一种灵活的规则描述语言和ixn的信任规则执行机制来实现。
(5)基于属性证书的访问控制:访问权限信息存放在用户属性证书的权限属性中,每个权限属性描述了一个或多个用户的访问权限。但用户对某一资源提出访问请求时,系统根据用户的属性证书中的权限来判断是否允许或拒绝。
RBAC
RBAC(Role-Based Access Control)-基于角色的访问控制,模型是20世纪90年代研究出来的一种新模型,但从本质上讲,这种模型是对前面描述的访问矩阵模型的扩展。这种模型的基本概念是把许可权(Permission)与角色(Role)联系在一起,用户通过充当合适橘色的成员而获得该角色的许可权。在实际的组织中,为了完成组织的业务工作,需要在组织内部设置不同的职位,职位既标识一种业务分工,又标识一种责任与权利。根据业务分工的需要,职位被划分给不同群体,各个群体的人根据其工作任务的需要被赋予不同的职责和权力,每个人有权了解与使用与自己任务相关的信息与资源,对于那些不应该被知道的信息则应该限制他们访问,这就产生了访问控制的需求。
【例子】在一个大学中,有校长,副校长,训练部长,组织处长,科研处长,教保处长等不同的职位,在通常情况下,职位所赋予的权利是不变的,但在某个职位上的工作的人可以根据需要调整,RBAC模型对组织内部的这些关系与访问控制要求给出了非常恰当的描述。
RBAC重要对象:
1.用户(User):角色施加的主体;用户通过拥有某个或多个角色以得到对应的权限
2.角色(Role):一组权限的集合
3.权限(Permission):用户限定能够访问的一个资源【注意】
一个用户拥有若干角色,一个角色拥有若干权限,这样就构成了用户-角色-权限的授权模型。1.权限
RBAC模型(Role-Based Access Control:基于角色的访问控制)RBAC的组成:用户、角色和权限。
User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
Role(角色):不同角色具有不同的权限
Permission(权限):访问权限
用户-角色映射:用户和角色之间的映射关系
角色-权限映射:角色和权限之间的映射1.1 五张表的权限
用户信息表(T_User)
角色信息表(T_Role)
模块信息表(T_Module)
用户角色表(T_User_Role)
角色模块表(T_Role_Module)
角色权限表1.2 关系
用户角色表(T_User_Role) 角色模块表(T_Role_Module)
用户------------------------>角色------------------------->权限
(T_User) (T_Role) (T_Module)
表的组成
用户表:主键id,用户名,用户邮箱,是否为管理员,状态,创建时间,更新时间,...... 角色表:角色id,角色名,状态,创建时间,更新时间 权限表(菜单权限表):权限id,权限标题,权限父级id,图标,权限路径,状态,排序,创建时间,更新时间,...... 用户角色表:主键id,用户id,角色id,创建时间,更新时间 角色权限表:主键id,角色id,权限id,创建时间,更新时间,......
实现一下树形菜单显示 权限表 准备 数据库jdbc架包 与json格式转换架包
json架包下载
文件密码:2ab9
准备表
/*权限表(菜单表)*/ create table tb_promission ( id number primary key,--权限id text varchar2(100) not null,--权限名称 pid number not null,--权限父级id icon varchar2(100),--菜单显示的icon url varchar2(100),--权限资源路径 state number,--状态;该记录是否有效1:有效、0:无效 sort number--排序码 ) --基本的几条数据 insert into tb_promission(id,text,pid,icon,url,state,sort) values (1,'店铺管理',-1,'','',1,1); insert into tb_promission(id,text,pid,icon,url,state,sort) values (6,'店铺添加',1,'','/addshop.jsp',1,6); insert into tb_promission(id,text,pid,icon,url,state,sort) values (7,'店铺列表',1,'','/shopList.jsp',1,7);
权限实体编写 注意实体名须与官网api文档中属性保持一致否则无效
package com.zking.easyui.book.entity; import java.io.Serializable; import java.util.ArrayList; import java.util.List; //权限菜单的实体 public class Promission implements Serializable{ private static final long serialVersionUID = 1L; private Integer id; private String text; private Integer pid; private String icon; private String url; private Integer state; private Integer sort; //定义一个集合 保存指定一级菜单中的所有子节点 private List<Promission> children = new ArrayList<>(); public List<Promission> getChildren() { return children; } public void setChildren(List<Promission> children) { this.children = children; } public Promission() { // TODO Auto-generated constructor stub } public Promission(String text, Integer pid, String icon, String url, Integer state, Integer sort) { super(); this.text = text; this.pid = pid; this.icon = icon; this.url = url; this.state = state; this.sort = sort; } public Promission(Integer id, String text, Integer pid, String icon, String url, Integer state, Integer sort) { super(); this.id = id; this.text = text; this.pid = pid; this.icon = icon; this.url = url; this.state = state; this.sort = sort; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Integer getPid() { return pid; } public void setPid(Integer pid) { this.pid = pid; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Integer getState() { return state; } public void setState(Integer state) { this.state = state; } public Integer getSort() { return sort; } public void setSort(Integer sort) { this.sort = sort; } public static long getSerialversionuid() { return serialVersionUID; } @Override public String toString() { return "Promission [id=" + id + ", text=" + text + ", pid=" + pid + ", icon=" + icon + ", url=" + url + ", state=" + state + ", sort=" + sort + ", children=" + children + "]"; } }
dao方法的编写
package com.zking.easyui.book.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.zking.easyui.book.dao.IPromissonDao; import com.zking.easyui.book.entity.Promission; import com.zking.easyui.book.util.DBHelper; public class PromissonDaoImpl implements IPromissonDao { @Override public List<Promission> getPromissionAll(Integer pid) { Connection conn = null;//连接对象 PreparedStatement ps = null;//执行对象 ResultSet rs = null;//结果集对象 List<Promission> list = new ArrayList<Promission>();//集合 String sql = null;//sql Promission promission = null;//实体 try { //获取数据库连接 conn = DBHelper.getConn(); //sql sql = "select id,text,pid,icon,url,state,sort from tb_promission where pid = ? order by sort asc"; //ps ps = conn.prepareStatement(sql); //占位符 ps.setInt(1, pid); //rs rs = ps.executeQuery(); while(rs.next()) { promission = new Promission(); //设置 promission.setId(rs.getInt(1)); promission.setText(rs.getString(2)); promission.setPid(rs.getInt(3)); promission.setIcon(rs.getString(4)); promission.setUrl(rs.getString(5)); promission.setState(rs.getInt(6)); promission.setSort(rs.getInt(7)); list.add(promission); } } catch (Exception e) { e.printStackTrace(); }finally { } return list; } public static void main(String[] args) { List<Promission> promissionAll = new PromissonDaoImpl().getPromissionAll(-1); for (Promission promission : promissionAll) { System.out.println(promission); } } }
业务逻辑层工作查找所有子节点通过递归方式
package com.zking.easyui.book.biz.impl; import java.util.List; import com.zking.easyui.book.biz.IPromissionBiz; import com.zking.easyui.book.dao.IPromissonDao; import com.zking.easyui.book.dao.impl.PromissonDaoImpl; import com.zking.easyui.book.entity.Promission; public class PromissonBizImpl implements IPromissionBiz{ //需求:在业务逻辑层中根据一级菜单获取所有的对应的子节点 //实例化数据访问层即可 private IPromissonDao ipd = new PromissonDaoImpl(); // Promission 属性children(集合) @Override public List<Promission> getPromissionAll(Integer pid) { List<Promission> promissionAll = ipd.getPromissionAll(pid); for (Promission promission : promissionAll) { //如果遍历的promission中的url为空 说明该节点是一级菜单 //重新调用该方法传入该一级菜单的id ---》所有子节点 if(promission.getUrl() == null || "".equals(promission.getUrl())) { //根据遍历的一级菜单的id获取所有的子节点 List<Promission> promissionAll2 = getPromissionAll(promission.getId()); //设置到该一级菜单中的children属性中(集合) promission.setChildren(promissionAll2); } } //return ipd.getPromissionAll(pid); return promissionAll; } public static void main(String[] args) { List<Promission> promissionAll = new PromissonBizImpl().getPromissionAll(-1); for (Promission promission : promissionAll) { System.out.println(promission); } } }
servlet界面处理获取的数据
package com.zking.easyui.book.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; import com.zking.easyui.book.biz.IPromissionBiz; import com.zking.easyui.book.biz.impl.PromissonBizImpl; import com.zking.easyui.book.entity.Promission; /** * 获取权限表的servlet */ @WebServlet("/PromissionListServlet") public class PromissionListServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //V1.0 // 1.设置编码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("utf-8"); // text/html;charset=utf-8 response.setContentType("application/json;charset=utf-8"); // 2.获取请求参数(省略) // 3.根据获取的参数处理请求 // 实例化biz IPromissionBiz ipb = new PromissonBizImpl(); List<Promission> promissionAll = ipb.getPromissionAll(-1); // 4.响应 // 获取JSON工具 ObjectMapper mapper = new ObjectMapper(); String result = mapper.writeValueAsString(promissionAll); //获取out PrintWriter out = response.getWriter(); out.write(result); out.flush(); out.close(); } }
通过easy简单布局的后台界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <!-- 页面缓存 --> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="static/common/easyui-link.jsp"%> </head> <!-- 首页布局 --> <body class="easyui-layout" data-options="fit:true"> <div data-options="region:'north',title:'后台管理系统',split:true" style="height: 100px;"></div> <div data-options="region:'south',title:'底部版权信息',split:true" style="height: 100px;">底部版权信息</div> <div data-options="region:'west',title:'菜单管理',split:true" style="width: 200px;"> <!-- 1.树形菜单 --> <!-- 组件的实现: 1.纯标签+class = easyui-tree 2.标签+js --> <!-- 创建UL容器即可实现搭建tree树形菜单 --> <ul id = "menuTree"></ul> </div> <div data-options="region:'center',title:'内容区域'" style="padding: 5px; background: #eee;"> <!-- panel面板 --> <div style = "margin:0px;padding:0px" id="p" class="easyui-panel" data-options="fit:true,closable:true,collapsible:true,minimizable:true,maximizable:true"> <!-- 选项卡区域 --> <div id="myTabs" class="easyui-tabs" data-options = "fit:true"></div> </div> </div> <!-- js --> <script type="text/javascript"> //加载 $(function(){ //通过脚本的方式实现树形菜单 $("#menuTree").tree({ url:xPath+"/PromissionListServlet", //设置节点的点击事件 onClick:function(node){//node 代表节点,点击 就能获取当前所点击的节点对象,根据node拿到指定的属性 //console.log(node); //点击选项是,动态生成一个选项卡。 addTabs(node); } }); }); //封装一个函数存储添加选项卡的代码 function addTabs(node) { //alert(node.url); //如果没有url 则不生成tab选项卡 if(node.url===null || node.url==="" || node.url === undefined){ return; } //去重 let flag = $("#myTabs").tabs('exists',node.text); if(flag){ $("#myTabs").tabs('select',node.text); return; } //console.log(node); $("#myTabs").tabs('add', { //设置选项卡的标题 title : node.text, //设置选项的关闭按钮 closable : true, //选项卡内容 content : "<iframe src = '"+xPath+node.url+"' border='0' width = '100%' height = '100%'>" }); } </script> </body> </html>
实现效果