RBAC基於角色的權限管理--設計篇1.0
RBAC是什麼
基於角色的權限管理。簡單來說就是一個用戶可以擁有若干個角色,一個角色可以擁有若干個權限。這樣就形成了“用戶-角色-權限”的模型。
基礎表設計
- 數據庫採用MySql
- 這裏表設計只採用最基礎的字段
- 忽略字段長度,如採用此設計,請自行修改
- 忽略外鍵建設,如採用此設計,請自行建立
用戶表
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`create_time` datetime DEFAULT NULL COMMENT '創建時間',
`create_user` datetime DEFAULT NULL COMMENT '創建人',
`login_time` datetime DEFAULT NULL COMMENT '登錄時間',
`name` varchar(255) DEFAULT NULL COMMENT '用戶名稱',
`password` varchar(255) DEFAULT NULL COMMENT '登錄密碼',
`remark` varchar(255) DEFAULT NULL COMMENT '備註',
`status` int(11) DEFAULT NULL COMMENT '用戶狀態',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`update_user` datetime DEFAULT NULL COMMENT '更新人員',
`username` varchar(255) DEFAULT NULL COMMENT '登錄名稱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
角色表
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色id',<br/>
`role_name` varchar(255) DEFAULT NULL COMMENT '角色名稱',
`remark` varchar(255) DEFAULT NULL COMMENT '備註',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
權限表
CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '權限ID',
`permission_code` varchar(255) DEFAULT NULL COMMENT '權限編碼',
`permission_name` varchar(255) DEFAULT NULL COMMENT '權限名稱',
`pid` int(11) DEFAULT NULL COMMENT '父類權限ID(依賴權限)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
用戶角色關係表
CREATE TABLE `t_user_role` (
`user_id` int(11) NOT NULL COMMENT '用戶id',
`role_id` int(11) NOT NULL COMMENT '角色id',
PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
角色權限關係表
CREATE TABLE `t_role_permission` (
`role_id` int(11) NOT NULL COMMENT '角色id',
`permission_id` int(11) NOT NULL COMMENT '權限id',
PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
權限控制
控制菜單
場景
管理員和普通會員。如管理員可以看到所有菜單,普通會員只能看到一部分菜單(或可以看到,但點擊時彈出沒有權限操作的提示。由於個人喜好和個人體驗度偏差的原因,此文章中不採取這種方式)。
問題來了,如何控制角色的菜單權限?let‘s go!!!
表設計
CREATE TABLE `t_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`menu_name` varchar(255) DEFAULT NULL COMMENT '菜單名稱',
`permission_code` varchar(255) DEFAULT NULL COMMENT '權限編碼(菜單編碼)',
`pid` int(11) DEFAULT NULL COMMENT '父菜單id',
`url` varchar(255) DEFAULT NULL COMMENT '菜單url跳轉鏈接',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
簡要業務流程圖
詳細業務流程圖
控制按鈕
場景
擁有了菜單權限,依舊不能滿足某些場景的需要。例如多個角色在同時擁有A菜單的情況下,角色1可以有查詢,創建的權限,角色2則擁有查詢,創建,修改,刪除的權限。即角色1只能看到查詢,創建的按鈕,角色2可以看到查詢,創建,修改,刪除的按鈕。這個時候,我們應該如何處理呢?
實現
-
按鈕權限定義:在菜單權限下定義下級權限查詢,創建,修改,刪除,例如Aquery,Aadd,Aupdate,Adelete。
-
這裏結合shiro使用(不會使用的小夥伴請留言,後期補上解決方式):在A菜單跳轉的頁面中使用shiro:hasPermission則可以達到控制按鈕的效果。例如
<shiro:hasPermission name="Aadd"> <button>新建<button> </shiro:hasPermission>
詳細業務流程圖(結合shiro)
代碼示例(思想很重要)
檢查用戶是否有菜單權限
/**
* 檢查用戶是否有菜單權限
*
* @param menus
* 所有菜單
* @param subject
* shiro用戶信息
* @return 用戶已分配的菜單集合
*/
private List<Menu> check(List<Menu> menus, Subject subject) {
List<Menu> res = new ArrayList<Menu>();
for (Menu m1 : menus) {
if (StringUtils.isEmpty(m1.getPermissionCode())) {
continue;
}
// 這裏會觸發鑑權操作
if (subject.isPermitted(m1.getPermissionCode())) {
res.add(m1);
}
}
return res;
}
自定義realm-鑑權操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 查詢當前用戶所有權限
List<Permission> infos = userService.findMyPermitions();
// 權限集合(這裏我習慣把權限編碼放進去)
Set<String> permissions = new HashSet<String>();
// 角色集合(這裏放角色ID)
Set<String> roles = new HashSet<String>();
if (infos != null && infos.size() > 0) {
for (Permission info : infos) {
permissions.add(info.getPermissionCode());
roles.add(info.getRoleId());
}
}
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setStringPermissions(permissions);
authorizationInfo.setRoles(roles);
return authorizationInfo;
}
數據權限
場景
有些業務可能會是這樣。一個列表(或表格),要求普通用戶只能看到自己創建的列表信息,業務部門經理只能看到本部門的所有列表信息。這種權限如何控制?
實現
看反應,下回見。