RBAC基于角色的權限管理–設計篇1.0
RBAC是什麼
基于角色的權限管理。簡單來說就是一個使用者可以擁有若幹個角色,一個角色可以擁有若幹個權限。這樣就形成了“使用者-角色-權限”的模型。
基礎表設計
- 資料庫采用MySql
- 這裡表設計隻采用最基礎的字段
- 忽略字段長度,如采用此設計,請自行修改
- 忽略外鍵建設,如采用此設計,請自行建立
使用者表
CREATE TABLE `t_user` (
`id` int() NOT NULL AUTO_INCREMENT COMMENT
`create_time` datetime DEFAULT NULL COMMENT '建立時間',
`create_user` datetime DEFAULT NULL COMMENT '建立人',
`login_time` datetime DEFAULT NULL COMMENT '登入時間',
`name` varchar() DEFAULT NULL COMMENT '使用者名稱',
`password` varchar() DEFAULT NULL COMMENT '登入密碼',
`remark` varchar() DEFAULT NULL COMMENT '備注',
`status` int() DEFAULT NULL COMMENT '使用者狀态',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`update_user` datetime DEFAULT NULL COMMENT '更新人員',
`username` varchar() DEFAULT NULL COMMENT '登入名稱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8;
角色表
CREATE TABLE `t_role` (
`id` int() NOT NULL AUTO_INCREMENT COMMENT '角色id',
`role_name` varchar() DEFAULT NULL COMMENT '角色名稱',
`remark` varchar() DEFAULT NULL COMMENT '備注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8;
權限表
CREATE TABLE `t_permission` (
`id` int() NOT NULL AUTO_INCREMENT COMMENT '權限ID',
`permission_code` varchar() DEFAULT NULL COMMENT '權限編碼',
`permission_name` varchar() DEFAULT NULL COMMENT '權限名稱',
`pid` int() DEFAULT NULL COMMENT '父類權限ID(依賴權限)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8;
使用者角色關系表
CREATE TABLE `t_user_role` (
`user_id` int() NOT NULL COMMENT '使用者id',
`role_id` int() NOT NULL COMMENT '角色id',
PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
角色權限關系表
CREATE TABLE `t_role_permission` (
`role_id` int() NOT NULL COMMENT '角色id',
`permission_id` int() NOT NULL COMMENT '權限id',
PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
權限控制
控制菜單
場景
管理者和普通會員。如管理者可以看到所有菜單,普通會員隻能看到一部分菜單(或可以看到,但點選時彈出沒有權限操作的提示。由于個人喜好和個人體驗度偏差的原因,此文章中不采取這種方式)。
問題來了,如何控制角色的菜單權限?let‘s go!!!
表設計
CREATE TABLE `t_menu` (
`id` int() NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`menu_name` varchar() DEFAULT NULL COMMENT '菜單名稱',
`permission_code` varchar() DEFAULT NULL COMMENT '權限編碼(菜單編碼)',
`pid` int() DEFAULT NULL COMMENT '父菜單id',
`url` varchar() DEFAULT NULL COMMENT '菜單url跳轉連結',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8;
簡要業務流程圖

詳細業務流程圖
控制按鈕
場景
擁有了菜單權限,依舊不能滿足某些場景的需要。例如多個角色在同時擁有A菜單的情況下,角色1可以有查詢,建立的權限,角色2則擁有查詢,建立,修改,删除的權限。即角色1隻能看到查詢,建立的按鈕,角色2可以看到查詢,建立,修改,删除的按鈕。這個時候,我們應該如何處理呢?
實作
- 按鈕權限定義:在菜單權限下定義下級權限查詢,建立,修改,删除,例如Aquery,Aadd,Aupdate,Adelete。
- 這裡結合shiro使用(不會使用的小夥伴請留言,後期補上解決方式):在A菜單跳轉的頁面中使用則可以達到控制按鈕的效果。例如
<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() > ) {
for (Permission info : infos) {
permissions.add(info.getPermissionCode());
roles.add(info.getRoleId());
}
}
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setStringPermissions(permissions);
authorizationInfo.setRoles(roles);
return authorizationInfo;
}
資料權限
場景
有些業務可能會是這樣。一個清單(或表格),要求普通使用者隻能看到自己建立的清單資訊,業務部門經理隻能看到本部門的所有清單資訊。這種權限如何控制?
實作
看留言反應,下回見。