mldong 快速开发框架权限系统设计与实现

一、权限系统的核心目标

  • 用户身份识别:支持用户名/密码登录、第三方授权登录。
  • 接口访问控制:通过注解方式实现接口级别的权限控制。
  • 动态权限分配:支持角色绑定菜单权限、用户绑定角色关系。
  • 在线用户管理:查看当前在线用户、强制登出或踢下线操作。
  • 多租户与字段级权限(可扩展):为后续功能预留空间。

二、RBAC 权限模型详解

核心概念

实体 描述
User 用户实体,存储用户基本信息
Role 角色实体,定义角色名称、编码等
Menu 菜单实体,包含菜单名、编码、应用标识
UserRole 用户与角色的关系表
RoleMenu 角色与菜单的关联表

数据库结构图解(ER 图)


三、Sa-Token 登录认证流程解析

登录接口 /sys/login

java 复制代码
@PostMapping("/sys/login")
@ApiOperation(value="登录")
public CommonResult<?> login(@RequestBody @Validated LoginParam param) {
    if(ConstantContextHolder.getCaptchaOpenFlag()){
        if(!captchaManager.validate(HttpServletUtil.getRequest())) {
            return CommonResult.fail(SysErrEnum.CAPTCHA_ERROR);
        }
    }
    return CommonResult.data(authService.login(param));
}

登录逻辑核心步骤:

  1. 验证码验证:根据配置决定是否启用验证码;
  2. 用户名/手机号 + 密码验证
    • 查询用户是否存在;
    • 验证密码是否正确;
  3. 自定义登录处理器:用于处理第三方登录逻辑(如 OAuth2、短信登录等);
  4. 生成 Token 并绑定用户信息:使用 Sa-Token 进行登录,并将用户信息注入 Token 中;
  5. 记录登录日志:成功/失败日志记录,便于后续审计。

四、接口权限控制实现

使用 @SaCheckPermission 注解

在控制器方法上添加注解即可实现权限控制:

java 复制代码
@PostMapping("/sys/role/save")
@ApiOperation(value = "添加角色")
@SaCheckPermission("sys:role:save")
public CommonResult<?> save(@RequestBody @Validated({Groups.Save.class}) RoleParam param) {
    roleService.save(param);
    return CommonResult.ok();
}

支持 OR/AND 权限组合

java 复制代码
@PostMapping("/sys/rbac/roleMenuIds")
@SaCheckPermission(value = {"sys:rbac:roleMenuIds","sys:rbac:saveRoleMenu"}, mode = SaMode.OR)
public CommonResult<List<Long>> roleMenuIds(@RequestBody RoleMenuParam param){
    return  CommonResult.data(rbacService.roleMenuIds(param.getRoleId()));
}

权限验证原理(AuthService)

java 复制代码
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
    LoginUser loginUser = LoginUserHolder.me();
    List<String> perms = new ArrayList<>();
    if (AdminTypeEnum.SUPER_ADMIN.getCode().equals(loginUser.getAdminType())) {
        perms.add(CommonConstant.SUPER_ADMIN_PERM_FLAG);
    } else {
        RbacService rbacService = SpringUtil.getBean(RbacService.class);
        perms.addAll(rbacService.getPermInCache(loginUser.getRoleIds(), loginUser.getAppCode()));
    }
    return perms;
}

五、角色权限分配机制

分配角色菜单权限 /sys/rbac/saveRoleMenu

java 复制代码
@PostMapping("/sys/rbac/saveRoleMenu")
@ApiOperation(value="添加角色菜单")
@SaCheckPermission("sys:rbac:saveRoleMenu")
public CommonResult<?> saveRoleMenu(@RequestBody List<RoleMenuParam> param) {
    boolean isSuccess = rbacService.saveRoleMenu(param);
    if(isSuccess) {
        return CommonResult.ok("添加角色菜单成功");
    } else {
        return CommonResult.fail("添加角色菜单失败");
    }
}

核心逻辑:

  • 删除旧缓存;
  • 清除已有菜单权限;
  • 重新插入新的角色菜单关系;
  • 异步刷新缓存(避免影响主线程性能);

获取角色菜单列表 /sys/rbac/roleMenuList

java 复制代码
@PostMapping("/sys/rbac/roleMenuList")
@ApiOperation(value="获取角色菜单列表")
@SaCheckPermission("sys:rbac:roleMenuList")
public CommonResult<List<MenuVO>> roleMenuList(@RequestBody @Validated RoleMenuPageParam param) {
    return CommonResult.data(rbacService.roleMenuList(param));
}

六、用户角色管理 /sys/user/grantRole

java 复制代码
@PostMapping("/sys/user/grantRole")
@ApiOperation(value = "授权角色")
@SaCheckPermission("sys:user:grantRole")
public CommonResult<?> grantRole(@RequestBody @Validated({UserRoleParam.GrantRole.class}) UserRoleParam param) {
    userService.grantRole(param.getUserId(), param.getRoleIdList());
    return CommonResult.ok();
}

动态刷新权限机制

  • 修改角色后会清空用户的 Token 缓存;
  • 下次请求时自动加载新权限;
  • 若需立即生效,可调用 StpUtil.logout(userId) 强制登出。

七、在线用户管理 /sys/user/onlineUserList

java 复制代码
@PostMapping("/sys/user/onlineUserList")
@ApiOperation(value = "获取在线用户列表")
@SaCheckPermission("sys:user:onlineUserList")
public CommonResult<List<LoginUser>> onlineUserList(@RequestBody @Validated UserPageParam param) {
    return CommonResult.data(userService.onlineUserList(param));
}

查看当前在线设备

java 复制代码
@PostMapping("/sys/user/onlineDevice")
@ApiOperation(value = "个人-获取在线设备")
public CommonResult<List<LoginUser>> onlineDevice() {
    return CommonResult.data(userService.onlineDevice(LoginUserHolder.getUserId()));
}

支持 Token 级别操作

  • 强制注销logoutByTokenValue
  • 踢下线kickoutByTokenValue

八、关键类职责划分一览表

类名 职责说明
AuthController 登录、退出、验证码、扮演用户、第三方账号绑定
UserService 用户 CRUD、角色绑定、修改密码、在线状态维护
RoleService 角色创建、更新、查询
MenuService 菜单资源创建、更新、查询
RbacService 角色权限分配、菜单权限查询、用户角色管理
AuthService 登录逻辑、权限计算、扮演用户逻辑
AuthInterceptor 自定义拦截器,用于演示环境限制访问

九、总结与建议

✅ 已有优势:

  • 基于 Sa-Token 实现,轻量且高性能;
  • 支持动态权限分配,实时生效;
  • 接口权限控制粒度细,支持 OR/AND 组合;
  • 提供完整的在线用户管理功能;
  • 支持第三方账号绑定,灵活扩展。

💡 可优化方向:

  • 权限变更日志记录:记录谁在何时修改了什么权限;
  • 字段级权限控制:未来可扩展支持数据字段级权限;
  • 多租户支持:为 SaaS 架构做准备;
  • 权限继承机制:角色之间支持继承关系,简化配置。

十、结语

欢迎关注【mldong】开源项目,后续将持续分享权限扩展、低代码平台构建等内容。

如果你也想打造一个灵活可扩展的权限系统,欢迎 Star 我们的开源项目 mldong

更多关于权限、低代码平台构建的内容,欢迎关注【mldong】公众号,第一时间获取更新通知!


📌 如需获取完整源码,请访问 Gitee 地址:

🔗 gitee.com/mldong/mldo...


💬 "你在权限系统中遇到过哪些坑?欢迎留言交流。"

相关推荐
前端付豪1 分钟前
美团 Flink 实时路况计算平台全链路架构揭秘
前端·后端·架构
MikeWe1 分钟前
理解深度学习框架计算图的动态图与静态图:机制、实现与应用
后端
Android洋芋6 分钟前
从零到一构建企业级TTS工具:实战指南与优化策略
后端
chanalbert6 分钟前
AI大模型提示词工程研究报告:长度与效果的辩证分析
前端·后端·ai编程
Android洋芋9 分钟前
深度解析Android音频焦点处理与实战开发:从无声问题到企业级解决方案
后端
用户30742971671589 分钟前
MCP协议重大更新:八大特性全面升级
架构
海风极客11 分钟前
Go语言开发小技巧&易错点100例(十七)
后端·面试·github
海风极客11 分钟前
Go语言开发小技巧&易错点100例(十六)
后端·面试·github
梅一一16 分钟前
JavaScript 通吃指南:从浏览器到你的LED灯
前端·javascript·后端
Microsoft Word22 分钟前
项目中后端如何处理异常?
java·spring boot·java-ee