通常我们的网站都有权限控制,就像一个公司有产品、开发、运维之分,各自负责各自的业务,相互独立,有相互协作,共同完成一个任务。拥有不同权限的用户查看不同的页面,进行不同的操作。
Shiro是一种轻量级的安全框架,主要是做登录验证,权限检查,相对 Spring Security 是要简单很多,源码也很清晰。
表结构
在这里我主要是针对后台的用户操作权限的设计:
1.定义用户表 sys_user,我在用户表里面没有定义有关授权方面的,这个后面在登陆方面才用到。
id int 用户id
user_name varchar 账号
nick_name varchar 昵称
user_img varchar 头像
user_address varchar 地址
sex varchar 性别
phone varchar 手机号
email varchar 邮箱
email_verified int 邮箱是否验证,0未验证,1已验证
money int money
user_grade int 用户层级 普通用户0 vip 1 超级vip2
state int 状态,0正常,1冻结
last_login_time datetime 最后登录时间
2,角色表 sys_role
id int
role_code varchar
role_name varchar 角色名称
role_type int 角色类型 1是管理角色 2是VIP角色
description varchar 角色描述
state int 状态:1有效;2删除
order_no int 排序
3,用户角色关系表 sys_users_roles
id int
user_id varchar 用户id
role_id varchar 角色id
4,权限表 sys_permission
id int
permission_name varchar 权限名称
description varchar 权限描述
url varchar 权限访问路径
permission_code varchar 权限标识
parent_id int 父级权限id
type int 类型 0:目录 1:菜单 2:按钮
sort int 排序
icon varchar 图标
state int 状态:1有效;2删除
5,角色权限表 sys_role_permissions
id int
role_id varchar 角色id
permission_id varchar 权限id
permission_type tinyint 权限类型 1为目录权限 2为板块权限 3为其他权限
结构如下

说明:
1,用户与角色的关系是一对多,一个用户可以有多个角色。
2,sys_menu后台菜单表也叫权限表。
3,sys_role_permission是角色权限表,一个角色是多个权限的集合,里面的permission_id可以包括多种权限,包括sys_menu里面的权限点。
4,根据上面的关系,就是一个用户包括多个角色,每个角色又包括多个权限,这样就可以将用户与角色,用户与权限点关联起来。
SQL
获取用户角色
<select id="listByUserId" resultMap="BaseResultMap">
SELECT
r.*
FROM
sys_user u,
sys_role r,
sys_users_roles ur
WHERE
u.id = #{userId}
AND u.id = ur.user_id
AND r.id = ur.role_id
</select>获取用户权限
<select id="listByUserId" resultMap="BaseResultMap">
SELECT
m.*
FROM
sys_user u,
sys_role r,
sys_users_roles ur,
sys_menu m,
sys_role_permissions rp
WHERE
u.id = #{userId}
AND u.id = ur.user_id
AND ur.role_id = r.id
AND r.id = rp.role_id
and rp.permission_id = m.id
and rp.permission_type = 1
</select>界面
用户管理

用户新增的时候可以选择角色(多选)

角色管理

角色编辑和角色权限分配


角色权限分配的时候,通过当前选择角色去后台查询角色对应的权限点,
/**
* 获取角色的菜单
*
* @param roleId
* @return
* @author JAVABB
*/
public List<MenuDO> listByRoleId(Integer roleId) {
List<MenuDO> permissionList;
if (roleId == Constant.ADMIN_ROLE_ID) { // 如果是管理员,拥有所有权限
permissionList = this.queryAll();
} else {
JSONObject param = new JSONObject();
param.put("sqlid", MenuMapper.class.getName() + ".listByRoleId");
param.put("roleId", roleId);
permissionList = this.queryList(param);
}
return permissionList;
}
/**
* 将权限封装成树
* @return
*/
public List<Tree> listTree() {
List<Tree> treeList = new ArrayList<>();
List<MenuDO> permissionList = this.queryAll();
permissionList.forEach(p -> {
Tree t = new Tree();
t.setId(p.getId() + "");
t.setParentId(p.getParentId() + "");
t.setName(p.getMenuName() + "/" + p.getPermissionCode());
treeList.add(t);
});
return treeList;
}
/**
* 根据roleId获取带勾选的树
*
* @param roleId
* @return
*/
public List<Tree> checkTreeByRoleId(Integer roleId) {
List<Tree> allTreeList = listTree();
List<MenuDO> checkPermissionList = listByRoleId(roleId);
for (Tree t : allTreeList) {
for (MenuDO p : checkPermissionList) {
if (t.getId().equals(p.getId() + "")) {
t.setChecked(true);
}
}
}
return allTreeList;
}通过方法checkTreeByRoleId就可以形成一个树
前台采用ztree树插件
var setting = {
check: {enable: true},
data: {
simpleData: {
enable: true,
idKey:"id",
pIdKey:"parentId",
rootPId:"1"
}
}
};
B.get({
url:'/admin/role/permissionTree',
data:{roleId,roleId},
success:function(res){
$.fn.zTree.init($('#menuPermissionTree'), setting, res.data.menuPermissionTree);
layer.closeAll('loading');
}
});权限管理


权限分为3中类型,菜单,目录,按钮