众筹项目 RBAC 角色模块

项目计划

  • RBAC 角色模块

第一章 RBAC权限模型
1.1 基础表模型
1.概念
权限管理,这是每个软件系统都会涉及到的,而且权限管理的需求本质往往都是一样,不同的角色拥有不同的权限,只要你充当了某个角色,你就拥有了相对应的功能。
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。
简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。
这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般都是多对多的关系

1.2 扩展表模型
1.2.1 扩展用户组

1.2.2 扩展更多权限控制元素

1.2.3 完整扩展模型

1.3 级别0
RBAC级别 - RABC0
RBAC0的模型中包括用户(U)、角色(R)和许可权(P)等3类实体集合。
RABC0权限管理的核心部分,其他的版本都是建立在0的基础上的,看一下类图:

1.4 级别1
RBAC1,基于RBAC0模型,引入角色间的继承关系,即角色上有了上下级的区别,角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构,实现角色间的单继承。

这种模型合适于角色之间的层次明确,包含明确。

1.5 级别2
RBAC级别 - RABC2
RBAC2,基于RBAC0模型的基础上,进行了角色的访问控制。

RBAC2模型中添加了责任分离关系。RBAC2的约束规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。约束与用户-角色-权限关系一起决定了RBAC2模型中用户的访问许可,此约束有多种。

互斥角色 :同一用户只能分配到一组互斥角色集合中至多一个角色,支持责任分离的原则。互斥角色是指各自权限互相制约的两个角色。对于这类角色一个用户在某一次活动中只能被分配其中的一个角色,不能同时获得两个角色的使用权。常举的例子:在审计活动中,一个角色不能同时被指派给会计角色和审计员角色。

基数约束 :一个角色被分配的用户数量受限;一个用户可拥有的角色数目受限;同样一个角色对应的访问权限数目也应受限,以控制高级权限在系统中的分配。例如公司的领导人有限的;

先决条件角色 :可以分配角色给用户仅当该用户已经是另一角色的成员;对应的可以分配访问权限给角色,仅当该角色已经拥有另一种访问权限。指要想获得较高的权限,要首先拥有低一级的权限。

运行时互斥 :例如,允许一个用户具有两个角色的成员资格,但在运行中不可同时激活这两个角色。

1.6 级别3
RBAC级别 - RABC3
RBAC3,也就是最全面级的权限管理,它是基于RBAC2的基础上,将RBAC1和RBAC2进行整合了,最全面,也最复杂的

总结
任何系统中都会涉及到权限管理的模块,无论复杂简单,我们都可以通过以RBAC模型为基础,进行相关灵活运用来解决我们的问题
基本模型RBAC0定义了完全支持RBAC概念的任何系统的最低需求。

RBAC1和RBAC2两者都包含RBAC0,但各自都增加了独立的特点,它们被称为高级模型。

RBAC1中增加了角色分级的概念,一个角色可以从另一个角色继承许可权。

RBAC2中增加了一些限制,强调在RBAC的不同组件中在配置方面的一些限制。

RBAC3称为统一模型,它包含了RBAC1和RBAC2,利用传递性,也把RBAC0包括在内。这些模型构成了RBAC96模型族。

1.7 ACL模型
ACL(Access Controller List)模型
访问控制列表,是前几年盛行的一种权限设计,它的核心在于用户直接和权限挂钩。
RBAC的核心是用户和角色关联,而角色代表了权限,这样设计的优势在于使得对用户而言,只需角色即可以,而某角色可以拥有各种各样的权限并可继承。

ACL和RBAC相比缺点在于由于用户和权限直接挂钩,导致在授予时的复杂性,虽然可以利用组来简化这个复杂性,但仍然会导致系统不好理解,而且在取出判断用户是否有该权限时比较的困难,一定程度上影响了效率。
1.8 基于RBAC模型的权限框架
Apache Shiro
参考官网视频: http://www.gulixueyuan.com/course/45
Spring Security
可以与Spring框架无缝集成
SELinux
第二章 查询角色
2.1 控制器

/**
 * 要什么数据发请求获取即可
 * @return
 */
@GetMapping("/index.html")
public String index(){
return "admin/role/list";
} 
/**
 * 获取所有角色列表。我们只返回有用的数据
 */
@ResponseBody
@GetMapping("/list")
public PageInfo<TRole> roleList(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "" + AppConst.PAGE_SIZE) Integer ps,
@RequestParam(value = "condition", defaultValue = "") String condition){ 
PageHelper.startPage(pn, ps);
List<TRole> roles = adminRoleService.selectAll(condition);
PageInfo<TRole> pageInfo = new PageInfo<>(roles,AppConst.NAV_PAGE_NUM); 
return pageInfo;
}

2.2 业务层

@Override
	public List<TRole> listByCondition(String condition) {		
		TRoleExample example = new TRoleExample();		
		if(!StringUtils.isEmpty(condition)) {
			example.createCriteria().andNameLike("%"+condition+"%");
			try {
				int id = Integer.parseInt(condition);			
				Criteria criteria  = example.createCriteria();
				criteria.andIdEqualTo(id);
				example.or(criteria);
			} catch (NumberFormatException e) {				
			}
		}		
		return tRoleMapper.selectByExample(example);
	}

2.3 测试
2.3.1 安装浏览器web端开发助手,可以美化json数据。
WEB前端助手(FeHelper)_v2019.01.0714.crx

2.4 异步请求代码

<script type="text/javascript">
	var pageN = {pn:1,condition:"",pages:""};
	 
	$(function(){
		//1、发请求,获取所有的角色数据
		initRoleData();
		//2、将这些数据解析显示在页面的指定位置
	})
 
	function initRoleData(){
		$.get("${appPath}/role/list",{pn:pageN.pn,condition:pageN.condition},function(data){
			//1、拿到数据以后,解析数据,放在页面指定位置(js对DOM的CRUD)
			//alert(typeof content); // Object
			//var str = JSON.stringify(content); //将js对象转为字符串
			//alert(typeof content); // String
			console.log(data); 
			pageN.pages = data.pages;
			//2、展示表格数据
			buildTableContent(data.list);
			//3、展示分页条数据
			buildPageNav(data);
		});
	}
//2、构建分页条
function buildPageNav(nav){
		$("ul.pagination").empty();
		var firstPage = "<li pn='1'><a href='#'>首页</a></li>";
		var prePage = "<li pn='"+nav.prePage+"'><a href='#'>上一页</a></li>";
		var nextPage = "<li pn='"+nav.nextPage+"'><a href='#'>下一页</a></li>";
		var lastPage = "<li pn='"+nav.pages+"'><a href='#'>末页</a></li>"; 
		$("ul.pagination").append(firstPage);
		if(nav.hasPreviousPage){
		    $("ul.pagination").append(prePage);
	    }

	    //中间的连续分页
	    $.each(nav.navigatepageNums,function(){
		    //判断正在遍历的页码,是否当前页,如果是高亮显示
		    var cur = "";
		    if(this == nav.pageNum){ //是当前页
			    cur = "<li pn='"+this+"' class='active'><a href='#'>"+this+"</a></li>";
		    }else{
			    cur = "<li pn='"+this+"'><a href='#'>"+this+"</a></li>";
		    }
		    $("ul.pagination").append(cur);
		});
		if(nav.hasNextPage){
		    $("ul.pagination").append(nextPage);
		}
		$("ul.pagination").append(lastPage);
	}
 
	//1、构建表格数据
	function buildTableContent(content){
		//1、清除掉之前数据
		$("#contentTable tbody").empty();
		//console.log(content);
		//var str = JSON.stringify(content);//将js对象转为字符串
		//$("#contentTable tbody").append(str);
		$.each(content,function(){
			//每一个数据都要成为一个tr放在表格中
			var btnGroup = $("<td></td>");
			btnGroup.append("<button rid='"+this.id+"' class='btn btn-success btn-xs glyphicon glyphicon-check'></button> ")
			btnGroup.append("<button rid='"+this.id+"'  class='itemEditBtn btn btn-primary btn-xs glyphicon glyphicon-pencil'></button> ")
			btnGroup.append("<button rid='"+this.id+"'  class='itemDeleteBtn btn btn-danger btn-xs glyphicon glyphicon-remove'></button> ");
			 
			console.log(this);
			 
			var tr = $("<tr></tr>");//创建这个元素
			tr.append("<td>"+this.id+"</td>");
			tr.append("<td><input type='checkbox'></td>");
			tr.append("<td>"+this.name+"</td>");
			tr.append(btnGroup);
			tr.appendTo("#contentTable tbody");
		})
	}
 
	// $(找到元素).click():只能给页面已经存在的元素绑事件,未来动态添加到页面的绑不上(后来通过dom的CRUD给页面放的元素都不能绑上事件)
	/* $("ul.pagination li").click(function(){
	alert("111");
	}); */
	//$(父/祖先元素选择器).on(事件名,"要绑定事件的元素选择器",回调函数)
	$("ul.pagination").on("click","li",function(){
		var pn = $(this).attr("pn");
		pageN.pn = pn;
		initRoleData();//初始化数据
	});
 
	//点击查询按钮
	$("#searchBtn").click(function(){
		//1、获取条件值
		var condition = $("#searchParam").val();
		pageN.condition = condition;
		initRoleData();
	});
</script>

第三章 模态框
3.1 查看文档
3.4 基本使用

//点击打开角色添加模态框
$("#popAddModalBtn").click(function(){
$('#roleAddModal').modal("show");
});
//点击打开角色添加模态框
$("#popAddModalBtn").click(function(){
$('#roleAddModal').modal({
show:true, //打开
backdrop:'static'
});
});
<div class="modal fade" id="roleAddModal" tabindex="-1" role="dialog">
	<div class="modal-dialog" role="document">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal">
				<span>&times;</span>
				</button>
				<h4 class="modal-title">角色新增</h4>
			</div>
			<div class="modal-body">
				<form>
				<div class="form-group">
					<label>角色名</label> 
					<input id="roleName" class="form-control" placeholder="输入角色名">
				</div>
				</form>
			</div>
			<div class="modal-footer">
				<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
				<button type="button" class="btn btn-primary" οnclick="saveRole()">保存</button>
			</div>
		</div>
	</div>
</div>

第四章 角色添加
4.1 控制器

/**
 * 角色添加
 * @param role
 * @return
 */
@ResponseBody
@PostMapping("/add")
public String roleSave(TRole role){ 
adminRoleService.addRole(role); 
return "ok";
}

4.2 业务层

@Override
public void addRole(TRole role) {
roleMapper.insertSelective(role);
}

4.3 Postman测试
https://www.getpostman.com/ 下载安装(另外一个Restlet Client)
Postman-win64-6.6.1-Setup.exe

4.4 ajax代码

//保存角色
function saveRole(){
//1、拿到数据
var roleName = $("#roleName").val();
//2、发送请求
$.post("${appPath}/role/add",{name:roleName},function(data){
if(data == "ok"){
//保存成功
//1、关闭模态框
$('#roleAddModal').modal('hide');
//2、去最后一页
pageN.pn = pageN.pages+1;
initRoleData();
}
})
}

第五章 角色修改
5.1 点击按钮

<button rid='"+this.id+"'  class='itemEditBtn btn btn-primary btn-xs glyphicon glyphicon-pencil'></button>
//点击修改按钮弹出模态框
$("tbody").on("click",".itemEditBtn",function(){
//1、打开模态框
$("#roleUpdateModal").modal({
show:true,
backdrop:'static'
});
//2、查询当前要修改用户的详细信息并回显
$.get("${appPath}/role/get",{id:$(this).attr("rid")},function(data){
//console.log(data);
$("#roleUpdateForm input[name='name']").val(data.name);
$("#roleUpdateForm input[name='id']").val(data.id);
});
});

5.2 显示模态框,并回显数据

<!-- 修改模态框 -->
<div class="modal fade" id="roleUpdateModal" tabindex="-1" role="dialog">
	<div class="modal-dialog" role="document">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal">
				<span>&times;</span>
				</button>
				<h4 class="modal-title">角色修改</h4>
			</div>
			<div class="modal-body">
				<form id="roleUpdateForm">
				<div class="form-group">
				<label>角色名</label> 
				<input type="hidden" name="id"/>
				<input class="form-control"  name="name"  placeholder="输入角色名">
				</div>
				</form>
			</div>
			<div class="modal-footer">
				<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
				<button type="button" class="btn btn-primary" οnclick="updateRole()">修改</button>
			</div>
		</div>
	</div>
</div>

5.3 提交修改

function updateRole(){
	//1、修改角色
	//1)、收集页面需要发送给服务器的数据
	var rname = $("#roleUpdateForm input[name='name']").val();
	var rid = $("#roleUpdateForm input[name='id']").val();
	//2)、组装好数据给服务器发请求
	$.post("${appPath}/role/update",{id:rid,name:rname},function(data){
		if(data == "ok"){
		//1、成功
		//关闭模态框
		$("#roleUpdateModal").modal('hide');
			initRoleData();
		}
	})
	//3)、处理服务器响应回来的数据
}

5.4 修改处理
5.4.1 控制器

//查询单个角色
@ResponseBody
@GetMapping("/get")
public TRole getRole(@RequestParam("id")Integer id){
return adminRoleService.getRoleById(id);
}
 
//接口
@ResponseBody
@PostMapping("/update")
public String roleUpdate(TRole role){
adminRoleService.updateRole(role);
return "ok";
}

5.4.2 服务层

@Override
public TRole getRoleById(Integer id) {
return roleMapper.selectByPrimaryKey(id);
}
 
@Override
public void updateRole(TRole role) {
roleMapper.updateByPrimaryKeySelective(role);
}

第六章 角色删除
6.1 控制器

@ResponseBody
@GetMapping("/delete")
public String delete (@RequestParam("ids")String ids){ 
	//1、处理ids为要删除的用户的集合
	List<Integer> userIds = new ArrayList<>();
	String[] split = ids.split(",");
	for (String str : split) {
		int id;
		try {
			id = Integer.parseInt(str);
			userIds.add(id);
		} catch (NumberFormatException e) {
		}
	}
	adminRoleService.deleteRoles(userIds);
	return "ok";
}

6.2 服务层

@Override
public void deleteRoles(List<Integer> userIds) {
TRoleExample example = new TRoleExample();
example.createCriteria().andIdIn(userIds);
roleMapper.deleteByExample(example);
}

6.3 页面ajax代码

//单个删除
$("tbody").on("click",".itemDeleteBtn",function(){
var id = $(this).attr("rid");
var index = layer.confirm("确认删除吗?",{btn:["是的","NO"]},function(){
$.get("${appPath}/role/delete?ids="+id,function(data){
//删除成功,刷新数据
initRoleData();
layer.close(index);
});
},function(){});
})
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值