文章目录
业务分析
进入主页之后,不同的用户,拥有不同的权限,所以不同的用户的左侧菜单是不相同的,根据用户等级与RBAC查询用户的权限,根据不同的用户的权限显示不同的菜单栏。
等级与模块对应关系
user表字段degree对应用户等级
用户User表中有一个字段
degree
,这个对应着用户的权限等级。
degree
用户等级与模块的对应关系:如果User的degree=0,说明是saas管理员,查询saas管理员所属模块。
如果User的degree=1, 说明是租用企业的管理员,查询租用企业的管理员所属模块。(没有SaaS管理)
其他的用户类型。统一根据用户的userId查询RBAC的表,查询其拥有的模块然后显示出来。
模块module表的belong=0,对应用户user表的degree=0,代表saas管理员,拥有belong=0的所有模块管理。
模块module表的belong=1,对应用户user表的degree=1,代表企业管理员,拥有belong=1的所有模块管理。
模块module字段belong对应用户degree等级
模块module表中有一个字段
belong
,这个对应着用户表user的degree等级。
belong = 0,对应degree = 0的SaaS管理员的模块权限。
belong = 1,对应degree = 1的企业管理员的模块权限。
belong = 其他,对应的是user表的degree = 其他,也就是非管理员的用户,通过RBAC权限表连接查询出对应的模块权限显示出来
sql语句查询不同用户的模块权限
#三种用户
# 平台管理员 - Sass菜单 degree==0 所属模块belong = 0
# 企业管理员 -除了Sass菜单之外的所有 degree==1 所属模块 belong=1
# 用户 查RBAC
SELECT * FROM pe_user WHERE degree=0; -- 查询是saas管理员的用户
SELECT * FROM ss_module WHERE belong=0; -- 查询saas管理员的模块
SELECT * FROM pe_user WHERE degree=1; -- 查询企业管理员的用户
SELECT * FROM ss_module WHERE belong=1; -- 查询企业管理员的模块
SELECT * FROM pe_user WHERE degree NOT IN(0,1); -- 查询不在0(SaaS管理员) 1(企业管理员)之间的所有用户,其他用户(非管理员)
SELECT * FROM ss_module WHERE belong NOT IN(0,1); -- 查询不在0(SaaS管理员) 1(企业管理员)之间的用户的模块权限
-- 通过id查询普通用户的模块权限(查询RBAC五张表)
-- 其实只需要连接3个表就可以查询数据,用户user查询角色包role,角色查模块,就可以获取到用的模块权限
-- 先根据用户user表查有什么角色role,再根据role角色表查有什么模块module,用户角色表,角色模块表
-- 显示内连接
SELECT DISTINCT m.* -- 只显示模块字段 通过distinct来去除重复值
FROM pe_role_user ru
INNER JOIN pe_role_module rm
ON ru.role_id=rm.role_id
INNER JOIN ss_module m
ON m.module_id=rm.module_id
WHERE ru.user_id='0f1f71fe-fe7c-4a44-a952-4f08bf5aa990'
-- where ru.user_id='33a90aec-47d1-4dc8-a6ad-d4f9a1440577'
ORDER BY module_id ASC;
字段parent_id 模块之间的从属关系
module表的字段parent_id,可以查询模块之间的从属关系。
-- 查找所有属于moduleId=2模块的子模块 select * from ss_module where parent_id = '2'
动态菜单实现
1. export_system_service子工程编写测试类测试不同角色的权限模块
degree =0 平台管理员 只能看 Sass菜单
degree =1 企业管理员 只能看 Sass菜单以外
degree =其他 用户员 根据RBAC表查询
分别测试degree=0,1,2的用户模块权限
TestModuleService
@Test
public void test08(){
// 平台管理员 - Sass菜单 degree==0 所属模块belong = 0
// 企业管理员 -除了Sass菜单之外的所有 degree==1 所属模块 belong=1
// 用户 通过查RBAC权限,获取权限模块
//通过user查询用户的模块权限
//如果用户的degree = 0或者1 就显示模块中belong对应 = 0或1的模块
// 否则就根据RBAC权限表,通过连接表来查询
User user = new User();
user.setUserId("18077bdb-8dd3-4aae-95a2-078c963f8416");
//user.setDegree(0); //测试SaaS管理员的模块信息
//user.setDegree(1); //测试企业管理员的模块权限
//degree!=0或1 也就是非SaaS管理员和企业管理员,具体模块权限要看管理员赋予多少显示多少
user.setDegree(2);//普通用户
//查询该登录用户user的所有模块的权限,一个 Module对象,就是左侧栏上的一个菜单项
List<Module> menus = iModuleService.findModulesByUser(user);
l.info("test08 degree = "+ user.getDegree() +"拥有的模块权限数目 = "+ menus.size() +"\nmenus="+menus);
}
2. export_system_service子工程的service接口和实现类
IModuleService
//查找用户的模块权限,显示左侧导航栏
List<Module> findModulesByUser(User user);
ModuleServiceImpl
//查找用户的模块权限信息
@Override
public List<Module> findModulesByUser(User user) {
//通过degree确定user身份,然后通过对应的belong来查找模块权限(针对degree = 0和1)
//degree ==0 平台管理员 只能看 Sass菜单的模块权限(也就是模块belong=0的模块)
//degree ==1 企业管理员 只能看 Sass菜单以外的企业模块权限(也就是模块belong=1的所有模块)
//degree ==其他 用户 根据RBAC表查询(管理员授予多少模块权限,就显示多少)
//给一个用户数据到service,service自己判断
if (user.getDegree() == 0) {//SaaS平台管理员
return iModuleDao.findByBelong("0");
} else if (user.getDegree() == 1) {//企业管理员
return iModuleDao.findByBelong("1");
} else {//普通用户
return iModuleDao.findByUserId(user.getUserId());
}
}
3. export_dao子工程写dao接口及其映射
IModuleDao
//查找belong从属的模块权限(也就是SaaS管理员和企业管理员的模块权限),只有degree = 0和1的通过这种方式
List<Module> findByBelong(String belong);//0是SaaS平台管理 1是企业管理员
//通过userId使用RBAC查找普通用户的权限(degree!=0和1,非管理员的其他用户权限查找方式)
List<Module> findByUserId(String userId);
IModuleDao.xml
<!-- 查找belong从属的模块权限(也就是SaaS管理员和企业管理员的模块权限),只有degree = 0和1的通过这种方式 -->
<select id="findByBelong" parameterType="string" resultMap="moduleMap">
select * from ss_module where belong = #{belong};
</select>
<!-- 通过userId使用RBAC查找普通用户的权限(degree!=0和1,非管理员的其他用户权限查找方式)
显示内连接查询(不需要查询五张表,只需要三张表就能查询出用户的模块权限)
只需要连接3个表就可以查询数据,用户user查询角色包role,角色查模块,就可以获取到用的模块权限
-->
<select id="findByUserId" parameterType="string" resultMap="moduleMap">
select distinct m.*
from
pe_role_user ru
inner join pe_role_module rm on ru.role_id=rm.role_id
inner join ss_module m on m.module_id=rm.module_id
where ru.user_id=#{userId}
order by module_id asc;
</select>
4. export_web_manager子工程编写controller
ModuleController
//用户登录
@RequestMapping(path = "/login", method = {RequestMethod.GET, RequestMethod.POST})
public String login(String email,String password){ //email邮箱 和 密码
//根据 email查询对应的用户
l.info("用户输入邮箱login email "+email);
l.info("用户输入密码login password "+password);
//通过email查找user
User user = iUserService.findUserByEmail(email);
l.info("邮箱对应的用户email user "+user);
if (user != null) {
//比较账号密码
if(user.getPassword().equals(password)){
l.info("密码正确,登录成功");
//密码输入正确,将登录的用户保存到session中
session.setAttribute("loginUser",user);
//查询用户的模块权限,显示到右侧的导航栏,一个 Module对象 就是左侧栏上的一个菜单项
List<Module> menus = iModuleService.findModulesByUser(user);
session.setAttribute("menus",menus);
//登录成功跳转到主页
return "redirect:/home/toMain";
}else{
l.info("密码错误,请重新输入");
request.setAttribute("error","邮箱或者密码不对,请重新输入");
return "forward:/login.jsp"; //返回登录页面
}
}else{
l.info("用户不存在(邮箱不存在)");
request.setAttribute("error","用户(邮箱)不存在");
return "forward:/login.jsp";
}
}
添加代码:
//查询用户的模块权限,显示到右侧的导航栏,一个 Module对象 就是左侧栏上的一个菜单项
List<Module> menus = iModuleService.findModulesByUser(user);
session.setAttribute("menus",menus);
7. export_web_manager子工程编写jsp页面
left_menu.jsp
左侧导航栏循环显示对应菜单
<%-- 通过登录用户,查询对应的菜单menus,然后显示 --%>
<c:forEach items="${sessionScope.menus}" var="item">
<c:if test="${item.ctype==0}">
<li class="treeview">
<%--一级菜单 --%>
<a href="#">
<i class="fa fa-cube"></i> <span>${item.name}</span>
<span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span>
</a>
<ul class="treeview-menu">
<c:forEach items="${sessionScope.menus}" var="item2">
<%-- 模块列表module的ctype字段,用于判断是几级菜单 --%>
<%-- 一级菜单的ctype==0 二级菜单的ctype==1 --%>
<%-- 二级的parentId(上级菜单)肯定与一级的moduleId是相等,才能显示在该菜单下面 --%>
<c:if test="${item2.ctype==1 && item2.parentId == item.moduleId}">
<%-- 二级菜单 --%>
<li id="${item2.moduleId}">
<!-- 此处的链接,先加项目地址再加数据库中的curl,点击跳转到curl地址 -->
<a onclick="setSidebarActive(this)" href="${path}/${item2.curl}"
target="iframe">
<i class="fa fa-circle-o"></i>${item2.name}
</a>
</li>
</c:if>
</c:forEach>
</ul>
</li>
</c:if>
</c:forEach>