SSM 单体框架 - 教育平台后台管理系统:权限模块开发

权限概念介绍权限:权利(能做的)和限制(不能做的),在权限范围内做好自己的事情认证: 验证用户名密码是否正确的过程授权: 对用户所能访问的资源进行控制(动态显示菜单、URL 级别的权限控制)实现权限系统的原因首先系统需要进行登陆才能访问其次不同登陆用户要有不同的权利,而且要有不同的菜单(例如财务经理针对系统中财务相关模块进行操作,人事经理针对系统中人事模块进行操作)权限控制基本原理ACL(Access Control Lists)ACL 是最早也是最基本的一种访问控制机制,它的原理非常简单
摘要由CSDN通过智能技术生成

权限概念介绍

权限:权利(能做的)和限制(不能做的),在权限范围内做好自己的事情

认证: 验证用户名密码是否正确的过程

授权: 对用户所能访问的资源进行控制(动态显示菜单、URL 级别的权限控制)

实现权限系统的原因

首先系统需要进行登陆才能访问

其次不同登陆用户要有不同的权利,而且要有不同的菜单(例如财务经理针对系统中财务相关模块进行操作,人事经理针对系统中人事模块进行操作)

权限控制基本原理

ACL(Access Control Lists)

ACL 是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行 CRUD 中的哪些操作。当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。总得来说,ACL 是一种面向资源的访问控制模型,它的机制是围绕“资源”展开的。

RBAC(Role-Based Access Control)

RBAC 是基于角色的访问控制,通过用户的角色来确定用户能否针对某项资源进行某项操作。RBAC 相对于 ACL 最大的优势就是它简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来,而用户与权限变成了间接关联。RBAC 模型使得访问控制,特别是对用户的授权管理变得非常简单和易于维护,因此有广泛的应用。

规则一:每个登陆的用户,可以有多个角色

规则二:每个角色又可以拥有多个权限(包含菜单和资源)

ACL:用户 -> 权限
RBAC:用户 -> 角色 -> 权限
权限系统经典五张表

用户表、角色表、权限表、用户角色中间表、角色权限中间表

权限模块功能分析

权限模块主要细分为角色模块、菜单模块、资源模块,将针对细分的三个模块进行具体功能实现,同时会完成用户登陆、用户关联角色及动态菜单显示

权限模块管理

实现以下功能

  • 角色列表 & 条件查询(角色模块)
  • 分配菜单(角色模块)
  • 删除角色(角色模块)
  • 菜单列表查询(菜单模块)
  • 查询菜单信息回显(菜单模块)
  • 资源分页&多条件查询(资源模块)
  • 用户登陆(用户模块)
  • 动态菜单展示(权限模块)
  • 用户关联角色(用户模块)

权限模块表设计

数据库表
  • user 用户表

  • roles 角色表

  • menu 菜单表

  • resource 资源表

  • resource_category 资源分类表

  • user_role_relation 用户角色中间表

  • role_menu_relation 角色菜单中间表

  • role_resource_relation 角色资源中间表

表关系介绍
ER 图

多个用户对多个角色

权限表由菜单表和资源表组成;菜单表和资源表对权限表进行了细粒度划分

多个角色对多个权限表;用户表和权限表没有直接关联,是通过角色表进行了间接关联

一个资源分类表对多个资源表

数据实体描述

角色表

CREATE TABLE `roles` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '角色id',
  `code` VARCHAR(100) NOT NULL COMMENT '角色code',
  `name` VARCHAR(200) DEFAULT NULL COMMENT '角色名称',
  `description` VARCHAR(500) DEFAULT NULL COMMENT '简介',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

菜单表

CREATE TABLE `menu` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `parent_id` INT(11) NOT NULL COMMENT '父菜单id',
  `href` VARCHAR(200) DEFAULT NULL COMMENT '菜单路径',
  `icon` VARCHAR(200) DEFAULT NULL COMMENT '菜单图标',
  `name` VARCHAR(200) DEFAULT NULL COMMENT '菜单名称',
  `description` VARCHAR(500) DEFAULT NULL COMMENT '描述',
  `order_num` INT(11) DEFAULT NULL COMMENT '排序号',
  `shown` TINYINT(2) DEFAULT '1' COMMENT '是否展示',
  `level` INT(11) NOT NULL COMMENT '菜单层级,从0开始',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';

资源表

CREATE TABLE `resource` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '资源id',
  `name` VARCHAR(200) NOT NULL COMMENT '资源名称',
  `url` VARCHAR(200) NOT NULL COMMENT '资源url',
  `category_id` INT(11) DEFAULT NULL COMMENT '分类id',
  `description` VARCHAR(500) DEFAULT NULL COMMENT '简介',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`),
  KEY `idx_category_id` (`category_id`)
) ENGINE=INNODB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4 COMMENT='资源表';

资源分类表

CREATE TABLE `resource_category` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(200) DEFAULT NULL COMMENT '分类名称',
  `sort` INT(4) DEFAULT NULL COMMENT '排序',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='资源分类表';

用户角色中间表

CREATE TABLE `user_role_relation` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '关系id',
  `user_id` INT(11) NOT NULL COMMENT '用户id',
  `role_id` INT(11) NOT NULL COMMENT '角色id',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='用户和角色关系表';

角色菜单中间表

CREATE TABLE `role_menu_relation` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `menu_id` INT(11) NOT NULL COMMENT '菜单id',
  `role_id` INT(11) NOT NULL COMMENT '角色id',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=302 DEFAULT CHARSET=utf8mb4 COMMENT='角色和菜单关系表';

角色资源中间表

CREATE TABLE `role_resource_relation` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '关系id',
  `resource_id` INT(11) NOT NULL COMMENT '资源id',
  `role_id` INT(11) NOT NULL COMMENT '角色id',
  `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(100) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(100) NOT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8mb4 COMMENT='角色和资源关系表';

权限管理 - 角色模块接口实现

角色列表查询 & 条件查询
需求分析

点击角色列表按钮进行角色列表展示

查看接口文档,进行编码
实体类 Role
public class Role {
   
    private Integer id;
    private String code;
    private String name;
    private String description;
    private Date createdTime;
    private Date updatedTime;
    private String createdBy;
    private String updatedBy;
	// getter setter toString ...
}
Dao 层 RoleMapper
public interface RoleMapper {
   
    List<Role> findAllRole(Role role);
}
<?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="com.renda.dao.RoleMapper">
    <select id="findAllRole" parameterType="Role" resultType="Role">
        select * from roles
        <where>
            <if test="name != null and name != '' ">
                and name = #{name}
            </if>
        </where>
    </select>
</mapper>
Service 层 RoleService
public interface RoleService {
   
    List<Role> findAllRole(Role role);
}
@Service
public class RoleServiceImpl implements RoleService {
   
    @Autowired
    private RoleMapper roleMapper;

    @Override
    public List<Role> findAllRole(Role role) {
   
        return roleMapper.findAllRole(role);
    }
}
Web 层 RoleController
@RestController
@RequestMapping("/role")
public class RoleController {
   
    @Autowired
    private RoleService roleService;

    @RequestMapping("/findAllRole")
    public ResponseResult findAllRole(@RequestBody Role role) {
   
        List<Role> roleList = roleService.findAllRole(role);
        return new ResponseResult(true, 200, "查询所有角色成功", roleList);
    }
}
Postman 测试接口
添加 & 修改角色
需求分析

新建:点击提交按钮,将页面内容保存到数据库

修改:点击编辑按钮,由前端实现数据回显,在回显页面进行数据修改,将修改后值更新到数据库中

查看接口文档,进行编码
Dao 层 RoleMapper
void saveRole(Role role);

void updateRole(Role role);
<!-- 新增角色 -->
<insert id="saveRole" parameterType="Role">
    insert into roles (`name`, `code`, `description`, `created_time`, `updated_time`, `created_by`, `updated_by`)
    values (#{name}, #{code}, #{description}, #{createdTime}, #{updatedTime}, #{createdBy}, #{updatedBy})
</insert>

<!-- 更新角色 -->
<update id="updateRole" parameterType="Role">
    update roles
    <trim prefix="set" suffixOverrides=",">
        <if test="name != null and name != ''">
            `name` = #{name},
        </if>
        <if test="code != null and code != ''">
            `code` = #{code},
        </if>
        <if test="description != null and description != ''">
            `description` = #{description},
        </if>
        <if test=" updatedTime != null">
            `updated_time` = #{updatedTime},
        </if>
        <if test="updatedBy != null and updatedBy != ''">
            `updated_by` = #{updatedBy}
        </if>
    </trim>
    <where>
        <if test="id != null and id != ''">
            `id` = #{id}
        </if>
    </where>
</update>
Service 层 RoleService
void saveRole(Role role);

void updateRole(Role role);
@Override
public void saveRole(Role role) {
   
    // 封装数据
    Date date = new Date();
    role.setCreatedTime(date);
    role.setUpdatedTime(date);
    if (role.getCreatedBy() == null || "".equals(role.getCreatedBy())) {
   
        role.setCreatedBy("system");
        role.setUpdatedBy("system");
    }
    // 调用 mapper 方法
    roleMapper.saveRole(role);
}

@Override
public void updateRole(Role role) {
   
    // 封装数据
    role.setUpdatedTime(new Date());
    if (role.getUpdatedBy() == null || "".equals(role.getUpdatedBy())) {
   
        role.setUpdatedBy("system");
    }
    // 调用 mapper 方法
    roleMapper.updateRole(role);
}
Web 层 RoleController
@RequestMapping("/saveOrUpdateRole")
public ResponseResult saveOrUpdateRole(@RequestBody Role role) {
   
    if (role.getId() == null) {
   
        // 添加
        roleService.saveRole(role);
        return new ResponseResult(true, 200, "添加角色成功", null);
    } else {
   
        // 更新
        roleService.updateRole(role);
        return new ResponseResult(true, 200, "更新角色成功", null);
    }
}
Postman 测试接口
分配菜单
需求分析

点击分配菜单,回显可选择菜单信息,并回显选中状态;点击保存按钮为角色保存所选择的菜单信息

查询所有菜单列表
实体类 Menu
public class Menu {
   
    // 主键 id
    private Integer id;
    // 父菜单 id
    private int parentId;
    // 菜单路径
    private String href;
    // 菜单图标
    private String icon;
    // 菜单名称
    private String name;
    // 描述
    private String description;
    // 排序号
    private int orderNum;
    // 是否展示
    private int shown;
    // 菜单层级,从 0 开始
    private int level;
    // 创建时间
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createdTime;
    // 更新时间
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updatedTime;
    // 创建人
    private String createdBy;
    // 更新人
    private String updatedBy;
    // 声明集合:当前父级菜单所关联的子级菜单
    private List<Menu> subMenuList;
    // getter setter toString ...
}
Dao 层 MenuMapper
public interface MenuMapper {
   
    List<Menu> findSubMenuListByPid(int pid);
}
<?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="com.renda.dao.MenuMapper">
    <resultMap id="menuResult" type="Menu">
        <id column="id" property="id"/>
        <result column="href" property="href"/>
        <result column="icon" property=
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值