背景:由于公司新的业务增加需要开发多种业务下的应用功能,部分功能需要支持实现共享,基于现有项目(单应用), 在尽量不改动现有功能的情况下实现此需求,本人阐述了如何设计用户权限方案,包括应用级和用户级权限控制,涉及角色、权限、菜单的划分的运用。
功能规划:系统使用统一的用户、角色搭配不同应用下配置对应的菜单, 现实各个模块的菜单权限的管理, 其他业务功能模块支持共享, 且应用之间菜单权限实现隔离。
实现方案:各个应用的web端与后台交互需要传递appid, 服务端根据会话中的appid执行对应的业务逻辑,业务数据呈现通过组织架构进行控制,即用户只能看到对应组织下的数据, 角色菜单权限功能使用切面的方式根据appid执行对应的数据表操作。
部分核心代码示例:
ThreadLocal对象:
public class MySupport {
/**
* 当前APP的ID
*/
public static ThreadLocal<AppIdEnum> appId = ThreadLocal.withInitial(() -> AppIdEnum.MOWER);
/**
* 获取appId对应的自定义权限表的后缀
* @return
*/
public static String getAppTableSuffix() {
return appId.get().getSuffix();
}
/**
* 会话清理
*/
public static void clear(){
appId.remove();
}
}
请求拦截器:
public class MyLocaleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 从 http 请求头中取出 appId
String appId = request.getHeader(CommonConstants.DEFAULT_APP_ID_COLUMN);
//用于接口不同的appId返回对应的appId下的菜单及权限
MySupport.appId.set(AppIdEnum.getEnumByCode(appId));
return true;
}
}
SysRoleMenuMapper.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.op.mapper.SysRoleMenuMapper">
<resultMap type="cn.common.entity.sys.SysRoleMenu" id="SysRoleMenuResult">
<result property="roleId" column="role_id" />
<result property="menuId" column="menu_id" />
</resultMap>
<select id="checkMenuExistRole" resultType="Integer">
select count(1) from t_sys_role_menu${@cn.common.entity.common.MySupport@getAppTableSuffix()} where menu_id = #{menuId}
</select>
<delete id="deleteRoleMenuByRoleId" parameterType="Long">
delete from t_sys_role_menu${@cn.common.entity.common.MySupport@getAppTableSuffix()} where role_id=#{roleId}
</delete>
<delete id="deleteRoleMenu" parameterType="Long">
delete from t_sys_role_menu${@cn.common.entity.common.MySupport@getAppTableSuffix()} where role_id in
<foreach collection="array" item="roleId" open="(" separator="," close=")">
#{roleId}
</foreach>
</delete>
<insert id="batchRoleMenu">
insert into t_sys_role_menu${@cn.common.entity.common.MySupport@getAppTableSuffix()}(role_id, menu_id) values
<foreach item="item" index="index" collection="list" separator=",">
(#{item.roleId},#{item.menuId})
</foreach>
</insert>
</mapper>