权限模块
1、权限概念介绍
- 权限:权利(能做的)和限制(不能做的),在权限范围内做好自己的事情,不该看的不看,不该做的不做
- 认证: 验证用户名密码是否正确的过程
- 授权: 对用户所能访问的资源进行控制(动态显示菜单、url级别的权限控制)
为什么要实现权限系统
首先系统需要进行登陆才能访问,其次不同登陆用户要有不同的权利,而且要有不同的菜单(例如财务经理针对系统中财务相关模块进行操作,人事经理针对系统中人事模块进行操作)
权限控制基本原理
- ACL(Access Control Lists,缩写ACL)
ACL是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。总得来说,ACL是一种面向资源的访问控制模型,它的机制是围绕“资源”展开的。 - 基于角色的访问控制RBAC(Role-Based Access Control)
RBAC是把用户按角色进行归类,通过用户的角色来确定用户能否针对某项资源进行某项操作。RBAC相对于ACL最大的优势就是它简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来,而用户与权限变成了间接关联。RBAC模型使得访问控制,特别是对用户的授权管理变得非常简单和易于维护,因此有广泛的应用
规则一:每个登陆的用户,可以有多个角色;
规则二:每个角色又可以拥有多个权限(包含菜单和资源);
2、权限模块功能分析
权限模块主要细分为角色模块、菜单模块、资源模块,将针对细分的三个模块进行具体功能实现,同时会完成用户登陆、用户关联角色及动态菜单显示
- 实现以下功能:
- 角色列表&条件查询(角色模块)
- 分配菜单(角色模块)
- 删除角色(角色模块)
- 菜单列表查询(菜单模块)
- 查询菜单信息回显(菜单模块)
- 资源分页&多条件查询(资源模块)
- 用户登陆(用户模块)
- 动态菜单展示(权限模块)
- 用户关联角色(用户模块)
3、权限管理模块表设计
4、权限管理(角色模块)接口实现
4.1、角色列表查询&条件查询
- 名称: findAllRole
- 描述: 查询菜单列表
- URL: http://localhost:8080/ssm-web/role/findAllRole
- 请求方式: POST
- 请求参数
{name:"角色名称"}
- 响应结果示例
{
"success": true,
"state": 200,
"message": "响应成功",
"content": [{
"id": 1,
"code": "ADMIN",
"name": "超级管理员",
"description": "后台管理员,初始拥有权限管理功能",
"createdTime": 1595230889000,
"updatedTime": 1595230889000,
"createdBy": "system",
"updatedBy": "system"
}
......
}
dao层
<select id="findAllRole" resultType="role" parameterType="role">
SELECT
id,
CODE,
NAME,
description,
created_time,
updated_time,
created_by,
updated_by
FROM roles
<where>
<if test="name != null and name != ''">
and name = #{name}
</if>
</where>
</select>
service层
@Service
@Transactional
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleMapper roleMapper;
@Override
public List<Role> findAllRole(Role role) {
return roleMapper.findAllRole(role);
}
}
web层
@RestController
@RequestMapping("/role")
public class RoleController {
@Autowired
private RoleService roleService;
/*查询角色列表信息*/
@RequestMapping("/findAllRole")
public ResponseResult findAllRole(@RequestBody Role role){
List<Role> allRole = roleService.findAllRole(role);
return new ResponseResult(true, 200, "角色列表查询成功", allRole);
}
}
4.2、分配菜单
4.2.1、查询所有菜单列表
- 名称: findAllMenu
- 描述: 为角色分配菜单
- URL: http://localhost:8080/ssm-web/menu/findAllMenu
- 请求方式: GET
- 请求参数示例:
http://localhost:8080/ssm-web/menu/findAllMenu
- 响应结果示例
content内容为 前端所需的JSON格式菜单数据, 方便在树形空间中展示
{
"success": true,
"state": 200,
"message": "响应成功",
"content": {
"parentMenuList": [{
"id": 1,
"parentId": -1,
"href": "",
"icon": "lock",
"name": "权限管理",
"description": "管理系统角色、菜单、资源",
"orderNum": 1,
"shown": 1,
"level": 0,
"createdTime": 1595230898000,
"updatedTime": 1595230898000,
"createdBy": "system",
"updatedBy": "system",
"subMenuList": [{
"id": 2,
"parentId": 1,
"href": "Role",
"icon": "lock",
"name": "角色列表",
"description": "管理系统角色",
"orderNum": 1,
"shown": 1,
"level": 1,
"createdTime": 1595230898000,
"updatedTime": 1595230898000,
"createdBy": "system",
"updatedBy": "system",
"subMenuList": []
}]
}]
dao层(自连接查询)
<select id="findSubMenuListByPid" resultMap="MenuResult">
select * from menu where parent_id = #{pid}
</select>
<resultMap id="MenuResult" type="menu">
<id column="id" property="id"></id>
<result column="href" property="href"></result>
<result column="icon" property="icon"></result>
<result column="name" property="name"></result>
<result column="parent_id" property="parentId"></result>
<result column="description" property="description"></result>
<result column="orderNum" property="order_num"></result>
<result column="shown" property="shown"></result>
<result column="created_time" property="createdTime"></result>
<result column="updated_time" property="updatedTime"></result>
<result column="created_by" property="createdBy"></result>
<result column="updated_by" property="updatedBy"></result>
<collection property="subMenuList" ofType="menu" select="com.lzy.dao.MenuMapper.findSubMenuListByPid" column="id"/>
</resultMap>
service层
@Service
@Transactional
public class MenuMapperImpl implements MenuService {
@Autowired
private MenuMapper menuMapper;
@Override
public List<Menu> findSubMenuListByPid(Integer pid) {
return menuMapper.findSubMenuListByPid(pid);
}
}
web层
@RestController
@RequestMapping("/menu")
public class MenuController {
@Autowired
private MenuService menuService;
/*查询所有菜单信息*/
@RequestMapping("/findAllMenu")
public ResponseResult findAllMenu(){
List<Menu> menuList = menuService.findSubMenuListByPid(-1);
HashMap<String, Object> map = new HashMap<>();
map.put("parentMenuList", menuList);
return new ResponseResult(true, 200, "查询所有菜单信息成功", map);
}
}
postman测试
4.2.2、根据角色ID查询关联菜单ID
- 名称: findMenuByRoleId
- 描述: 根据角色信息查询关联菜单
- URL: http://localhost:8080/ssm-web/role/findMenuByRoleId?roleId=4
- 请求方式: GET
- 请求示例:
http://10.1.194.181:8080/ssm-web/role/findMenuByRoleId?roleId=1
- 响应结果示例
content中的内容为: 当前角色关联的菜单ID
{
"success": true,
"state": 200,
"message": "响应成功",
"content": ["1","2","3","4","10"]
}
dao层
<select id="findMenuByRoleId" resultType="Integer" parameterType="Integer">
select m.id from roles r INNER JOIN role_menu_relation rm on r.id = rm.role_id
INNER JOIN menu m on rm.menu_id = m.id where r.id = #{id}
</select>
service层
@Override
public List<Integer> findMenuByRoleId(Integer roleId) {
return roleMapper.findMenuByRoleId(roleId);
}
web层
@RequestMapping("/findMenuByRoleId")
public ResponseResult findMenuByRoleId(@RequestParam Integer roleId){
List<Integer> menuByRoleId = roleService.findMenuByRoleId(roleId);
return new ResponseResult(true, 200, "根据角色iD查询关联菜单id成功", menuByRoleId);
}
postman测试
4.2.3、为角色分配菜单列表
- 名称: RoleContextMenu
- 描述: 为角色分配菜单
- URL: http://localhost:8080/ssm-web/role/RoleContextMenu
- 请求方式: POST
- 请求参数:
参数名称 | 参数说明 | 是否必须 | 数据类型 | 备注 |
---|---|---|---|---|
roleId | 角色id | true | int | |
menuIdList | 所选的菜单列表id | true | List |
- 请求参数示例:
{
"roleId": 4,
"menuIdList": [7, 8, 9, 15, 16, 17, 18]
}
- 响应参数示例:
{"success":true,"state":200,"message":"响应成功","content":""}
dao层
<delete id="deleteRoleContextMenu" parameterType="integer">
delete from role_menu_relation where role_id = #{id}
</delete>
<insert id="RoleContextMenu" parameterType="Role_menu_relation">
insert into role_menu_relation values(null,#{menuId},#{roleId},#{createdTime},#{updatedTime},#{createdBy},#{updatedby})
</insert>
service层
@Override
public void RoleContextMenu(RoleMenuVo roleMenuVo) {
// 清空中间件
roleMapper.deleteRoleContextMenu(roleMenuVo.getRoleId());
for (Integer integer : roleMenuVo.getMenuIdList()) {
Role_menu_relation roleMenuRelation = new Role_menu_relation();
roleMenuRelation.setRoleId(roleMenuVo.getRoleId());
roleMenuRelation.setMenuId(integer);
roleMenuRelation.setCreatedTime(new Date());
roleMenuRelation.setUpdatedTime(new Date());
roleMenuRelation.setCreatedBy("system");
roleMenuRelation.setUpdatedby("system");
roleMapper.RoleContextMenu(roleMenuRelation);
}
}
web层
@RequestMapping("/RoleContextMenu")
public ResponseResult RoleContextMenu(@RequestBody RoleMenuVo roleMenuVo){
roleService.RoleContextMenu(roleMenuVo);
return new ResponseResult(true, 200, "分配菜单成功", null);
}
postman层
4.2.4、删除角色
- 名称: deleteRole
- 描述: 删除角色
- URL: http://localhost:8080/ssm-web/role/deleteRole?id=5
- 请求方式: GET
- 请求示例
http://localhost:8080/ssm-web/role/deleteRole?id=5
- 响应示例:
{"success":true,"state":200,"message":"响应成功","content":""}
dao层
<delete id="deleteRole" parameterType="integer">
delete from roles where id = #{id}
</delete>
service层
@Override
public void deleteRole(Integer id) {
// 清空中间表
roleMapper.deleteRoleContextMenu(id);
roleMapper.deleteRole(id);
}
web层
@RequestMapping("/deleteRole")
public ResponseResult deleteRole(Integer id){
roleService.deleteRole(id);
return new ResponseResult(true, 200, "删除角色成功", null);
}
postman层
4.2.5、添加&修改角色
- 名称: saveOrUpdateRole
- 描述: 根据菜单ID 查询菜单信息
- URL: http://localhost:8080/ssm-web/role/saveOrUpdateRole
- 请求方式: POST
- 请求参数
参数名称 | 参数说明 | in | 是否必须 | 数据类型 | 备注 |
---|---|---|---|---|---|
id | 角色ID | false | int | 修改操作携带ID | |
name | 角色名称 | true | String | ||
code | 角色编码 | true | String | ||
description | 角色描述 | true | String |
- 请求参数示例
// 添加
{
"name":"资源管理员",
"code": "RE_MANAGER",
"description": "管理资源"
}
// 更新
{
"id":"6"
"name":"资源管理员",
"code": "RE_MANAGER",
"description": "管理资源"
}
- 响应参数:
参数名称 | 参数说明 | 类型 | schema |
---|---|---|---|
success | boolean | ||
state | integer(int32) | integer(int32) | |
message | string | ||
content | object |
- 响应示例:
{
"success": true,
"state": 200,
"message": "响应成功",
"content": ""
}
dao层
<insert id="saveRole" parameterType="role">
insert into roles values (null, #{code}, #{name}, #{description}, #{
createdTime}, #{updatedTime},#{createdBy},#{updatedBy})
</insert>
<update id="updateRole" parameterType="role">
update roles
<trim prefix="set" suffixOverrides=",">
<if test="code != null and code != ''">
code = #{code},
</if>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="updatedTime != null ">
updated_time = #{updatedTime},
</if>
</trim>
<where>
<if test="id != null and id != ''">
id = #{id}
</if>
</where>
</update>
service层
@Override
public void saveRole(Role role) {
// 补全信息
Date date = new Date();
role.setCreatedTime(date);
role.setUpdatedTime(date);
role.setCreatedBy("system");
role.setUpdatedBy("system");
roleMapper.saveRole(role);
}
@Override
public void updateRole(Role role) {
// 补全信息
role.setUpdatedTime(new Date());
roleMapper.updateRole(role);
}
web层
@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);
}
}
4.3、菜单模块
4.3.1、菜单列表查询
- 名称: findAllMenu
- 描述: 查询菜单列表
- URL: http://localhost:8080/ssm-web/menu/findAllMenu
- 请求方式: GET
- 请求参数示例
http://10.1.194.181:8080/ssm-web/menu/findAllMenu
- 响应结果示例
{
"success": true,
"state": 200,
"message": "响应成功",
"content": {
"pageNum": 1,
"pageSize": 10,
"size": 10,
"orderBy": null,
"startRow": 1,
"endRow": 10,
"total": 26,
"pages": 3,
"list": [{
"id": 1,
"parentId": -1,
"href": "",
"icon": "lock",
"name": "权限管理",
"description": "管理系统角色、菜单、资源",
"orderNum": 1,
"shown": 1,
"level": 0,
"createdTime": 1595230898000,
"updatedTime": 1595230898000,
"createdBy": "system",
"updatedBy": "system",
"subMenuList": []
},
{
"id": 2,
"parentId": 1,
"href": "Role",
"icon": "lock",
"name": "角色列表",
"description": "管理系统角色",
"orderNum": 1,
"shown": 1,
"level": 1,
"createdTime": 1595230898000,
"updatedTime": 1595230898000,
"createdBy": "system",
"updatedBy": "system",
"subMenuList": []
}......]
}
}
dao层
<select id="findAllMenu" resultType="Menu">
SELECT
id,
parent_id,
href,
icon,
NAME,
description,
order_num,
shown,
LEVEL,
created_time,
updated_time,
created_by,
updated_by
FROM menu
</select>
service层
@Override
public List<Menu> findAllMenu() {
return menuMapper.findAllMenu();
}
web层
@RequestMapping("/findAllMenu")
public ResponseResult findAllMenu(){
List<Menu> allMenu = menuService.findAllMenu();
return new ResponseResult(true, 200, "查询菜单列表成功", allMenu);
}
postman测试
4.3.2、查询菜单信息(回显)
- 名称: findMenuInfoById
- 描述: 根据菜单ID 查询菜单信息
- URL: http://localhost:8080/ssm-web/menu/findMenuInfoById
- 请求方式: GET
- 请求参数
参数名称 | 参数说明 | in | 是否必须 | 数据类型 | 备注 |
---|---|---|---|---|---|
id | 菜单id | true | int | 如果是新增菜单,则id值为 -1, 修改菜单 则为当前选择的id值 |
- 响应结果
参数名称 | 参数说明 | 类型 | 备注 |
---|---|---|---|
success | boolean | ||
state | integer(int32) | ||
message | string | ||
content | object | ||
menuInfo | 菜单信息 | Menu | 修改操作需要回显的菜单信息 |
parentMenuList | 菜单列表信息 | List<Menu | 所有的父子菜单列表信息 |
dao层
<select id="findSubMenuListByPid" resultMap="MenuResult">
select * from menu where parent_id = #{pid}
</select>
<resultMap id="MenuResult" type="menu">
<id column="id" property="id"></id>
<result column="href" property="href"></result>
<result column="icon" property="icon"></result>
<result column="name" property="name"></result>
<result column="parent_id" property="parentId"></result>
<result column="description" property="description"></result>
<result column="orderNum" property="order_num"></result>
<result column="shown" property="shown"></result>
<result column="created_time" property="createdTime"></result>
<result column="updated_time" property="updatedTime"></result>
<result column="created_by" property="createdBy"></result>
<result column="updated_by" property="updatedBy"></result>
<collection property="subMenuList" ofType="menu" select="com.lzy.dao.MenuMapper.findSubMenuListByPid" column="id"/>
</resultMap>
<select id="findMenuById" resultType="menu">
select * from menu where id = #{id}
</select>
service层
@Override
public Menu findMenuById(Integer id) {
return menuMapper.findMenuById(id);
}
@Override
public List<Menu> findSubMenuListByPid(Integer id) {
return menuMapper.findSubMenuListByPid(id);
}
web层
@RequestMapping("/findMenuInfoById")
public ResponseResult findMenuInfoById(@RequestParam Integer id){
if(id == -1){
/*添加操作*/
List<Menu> subMenuListByPid = menuService.findSubMenuListByPid(-1);
// 封装数据
Map<String, Object> map = new HashMap<>();
map.put("menuInfo", null);
map.put("parentMenuList", subMenuListByPid);
return new ResponseResult(true, 200, "菜单信息回显成功", map);
}else{
Menu menu = menuService.findMenuById(id);
List<Menu> subMenuListByPid = menuService.findSubMenuListByPid(-1);
// 封装数据
Map<String, Object> map = new HashMap<>();
map.put("menuInfo", menu);
map.put("parentMenuList", subMenuListByPid);
return new ResponseResult(true, 200, "菜单信息回显成功", map);
}
}
postman测试
4.3.3、添加&修改菜单
- 名称: saveOrUpdateMenu
- 描述: 保存和修改菜单
- URL: http://localhost:8080/ssm-web/menu/saveOrUpdateMenu
- 请求方式: POST
- 请求参数
参数名称 | 参数说明 | 是否必须 | 数据类型 | 备注 |
---|---|---|---|---|
id | 菜单列表id | 否 | int | 修改操作必须携带id,插入不需要携带 |
name | 菜单名称 | 是 | string | |
href | 菜单路径 | 是 | string | |
parentId | 父菜单id | 是 | int | |
description | 描述 | 是 | string | |
icon | 菜单图标 | 是 | string | |
shown | 是否展示 | 是 | int | |
orderNum | 排序号 | 是 | int | |
level | 菜单层级,从0开始 | 是 | int | |
createdTime | 创建时间 | 是 | date | |
updatedTime | 更新时间 | 是 | date | |
createdBy | 创建人 | 是 | string | |
updatedBy | 更新人 | 是 | string |
- 请求示例
//新增
{
"description": "设置课程状态",
"href": "updateStatus",
"icon": "lock",
"name": "课程管理状态",
"orderNum": 3,
"parentId": 5,
"shown": 0,
"level":0,
"createdTime":"2020-08-10 20:32:41",
"updatedTime":"2020-08-10 20:32:41",
"createdBy":"system",
"updatedBy":"system"
}
//修改
{
"id":23,
"description": "设置课程状态修改",
"href": "updateStatus修改",
"icon": "lock",
"name": "课程管理状态修改",
"orderNum": 3,
"parentId": 5,
"shown": 1,
"level":1,
"createdTime":"2020-08-10 20:32:41",
"updatedTime":"2020-08-10 20:32:41",
"createdBy":"system",
"updatedBy":"system"
}
dao层
<insert id="saveMenu" parameterType="menu">
insert into menu values(null, #{parentId}, #{href}, #{icon}, #{name}, #{description}, #{orderNum},
#{shown}, #{level}, #{createdTime}, #{updatedTime}, #{createdBy}, #{updatedBy})
</insert>
<update id="updateMenu" parameterType="menu">
update menu
<trim prefix="set" suffixOverrides=",">
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="href != null and href != ''">
href = #{href},
</if>
<if test="icon != null and icon != ''">
icon = #{icon},
</if>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="orderNum != null and orderNum != ''">
order_num = #{orderNum},
</if>
<if test="parentId != null and parentId != ''">
parent_id = #{parentId},
</if>
<if test="updatedTime != null">
updated_time = #{updatedTime}
</if>
</trim>
<where>
<if test="id != null and id != ''">
id = #{id}
</if>
</where>
</update>
service层
@Override
public void saveMenu(Menu menu) {
// 补全信息
Date date = new Date();
menu.setCreatedTime(date);
menu.setUpdatedTime(date);
menu.setCreatedBy("system");
menu.setUpdatedBy("system");
menuMapper.saveMenu(menu);
}
@Override
public void updateMenu(Menu menu) {
// 补全信息
Date date = new Date();
menu.setUpdatedTime(new Date());
menuMapper.updateMenu(menu);
}
web层
@RequestMapping("/saveOrUpdateMenu")
public ResponseResult saveOrUpdateMenu(@RequestBody Menu menu){
if(menu.getId() == null){
menuService.saveMenu(menu);
return new ResponseResult(true, 200, "保存菜单成功", null);
}else{
menuService.updateMenu(menu);
return new ResponseResult(true, 200, "修改菜单成功", null);
}
}
postman测试
4.4、资源模块
4.4.1、查询资源分类信息
- 名称: findAllResourceCategory
- 描述: 查询资源分类信息列表
- URL: http://localhost:8080/ssm-web/ResourceCategory/findAllResourceCategory
- 请求方式: GET
- 请求参数
无
- 响应结果示例
{
"success": true,
"state": 200,
"message": "响应成功",
"content": [
{
"id": 1,
"code": "ADMIN",
"name": "超级管理员",
"description": "后台管理员,初始拥有权限管理功能",
"createdTime": 1595230889000,
"updatedTime": 1595230889000,
"createdBy": "system",
"updatedBy": "system"
},
{
"id": 2,
"code": "AUTHORITY_MANAGER",
"name": "权限管理员",
"description": "管理权限相关数据,如角色、菜单、资源。可以给用户分配角色。",
"createdTime": 1595202475000,
"updatedTime": 1595202475000,
"createdBy": "15510792994",
"updatedBy": "15510792994"
},
{
"id": 3,
"code": "COURSE_MANAGER",
"name": "课程管理员",
"description": "管理课程信息,对课程、课时、章节进行管理。",
"createdTime": 1595202724000,
"updatedTime": 1595202724000,
"createdBy": "15510792994",
"updatedBy": "15510792994"
},
{
"id": 4,
"code": "AD_MANAGER",
"name": "广告管理员",
"description": "管理广告、广告位信息",
"createdTime": 1595202956000,
"updatedTime": 1595202956000,
"createdBy": "15510792994",
"updatedBy": "15510792994"
}
]
}
dao层
<select id="findAllResourceCategory" resultType="ResourceCategory">
select * from resource_category
</select>
service层
@Service
@Transactional
public class ResourceCategoryServiceImpl implements ResourceCategoryService {
@Autowired
private ResourceCategoryMapper resourceCategoryMapper;
@Override
public List<ResourceCategory> findAllResourceCategory() {
return resourceCategoryMapper.findAllResourceCategory();
}
}
web层
@RestController
@RequestMapping("/ResourceCategory")
public class ResourceCategoryController {
@Autowired
private ResourceCategoryService resourceCategoryService;
@RequestMapping("/findAllResourceCategory")
public ResponseResult findAllResourceCategory(){
List<ResourceCategory> allResourceCategory = resourceCategoryService.findAllResourceCategory();
return new ResponseResult(true, 200, "查询资源分类成功", allResourceCategory);
}
}
postman测试
4.4.2、资源信息分页&条件查询
- 名称: findAllResource
- 描述: 资源信息分页&条件查询
- URL: http://localhost:8080/ssm-web/resource/findAllResource
- 请求方式: POST
- 请求参数
参数名称 | 参数说明 | 类型 | 备注 |
---|---|---|---|
currentPage | 当前页 | int | |
pageSize | 每页显示条数 | int | |
name | 资源名称 | string | |
categoryId | 资源分类id | int | |
url | 资源路径 | string |
- 请求参数示例
{
categoryId: 1,
currentPage: 1,
name: "获取所有角色",
pageSize: 5,
url: "/boss/role/all"
}
- 响应结果示例
{
"success": true,
"state": 200,
"message": "响应成功",
"content": {
"pageNum": 1,
"pageSize": 5,
"size": 1,
"orderBy": null,
"startRow": 1,
"endRow": 1,
"total": 1,
"pages": 1,
"list": [{
"id": 1,
"name": "获取所有角色",
"url": "/boss/role/all",
"categoryId": 1,
"description": "获取所有角色",
"createdTime": 1595230917000,
"updatedTime": 1595230917000,
"createdBy": "system",
"updatedBy": "system"
}]
}
}
dao层
<select id="findAllResource" parameterType="resourseVo" resultType="Resource">
select * from resource
<where>
<if test="name != null">
and name like concat('%',#{name},'%')
</if>
<if test="url != null">
and url = url
</if>
<if test="categoryId != null">
and category_id = #{categoryId}
</if>
</where>
</select>
service层
@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {
@Autowired
private ResourceMapper resourceMapper;
@Override
public PageInfo<Resource> findAllResource(ResourseVo resourceVo) {
PageHelper.startPage(resourceVo.getCurrentPage(), resourceVo.getPageSize());
List<Resource> allResource = resourceMapper.findAllResource(resourceVo);
PageInfo<Resource> resourcePageInfo = new PageInfo<>(allResource);
return resourcePageInfo;
}
}
web层
@RestController
@RequestMapping("/resource")
public class ResourceController {
@Autowired
private ResourceService resourceService;
@RequestMapping("/findAllResource")
public ResponseResult findAllResource(@RequestBody ResourseVo resourseVo){
PageInfo<Resource> allResource = resourceService.findAllResource(resourseVo);
return new ResponseResult(true, 200, "资源查询成功", allResource);
}
}
postaman测试
4.4.3、添加&更新资源信息
- 名称: saveOrUpdateResource
- 描述: 添加&更新资源信息
- URL: http://localhost:8080/ssm-web/resource/saveOrUpdateResource
- 请求方式: POST
- 请求参数
参数名称 | 参数说明 | in | 是否必须 | 数据类型 | 备注 |
---|---|---|---|---|---|
id | 资源id | false | 修改操作需要携带ID | ||
name | 资源名称 | true | String | ||
url | 资源路径 | true | String | ||
categoryId | 所属资源分类 | true | Integer | ||
description | 资源描述 | true | String |
请求示例:
// 添加
{
"name":"获取所有角色2",
"url": "/boss/role/all",
"categoryId":"1",
"description":"获取所有角色1"
}
// 更新
{
"id":"53",
"name":"获取所有角色2",
"url": "/boss/role/all",
"categoryId":"1",
"description":"获取所有角色1"
}
响应参数:
参数名称 | 参数说明 | 类型 | schema |
---|---|---|---|
success | boolean | ||
state | integer(int32) | integer(int32) | |
message | string | ||
content | object |
dao层
<insert id="saveResource" parameterType="resource">
insert into resource values(null, #{name}, #{url}, #{categoryId}, #{description},
#{createdTime}, #{updatedTime}, #{createdBy}, #{updatedBy})
</insert>
<update id="updateResource" parameterType="resource">
update resource
<trim prefix="set" suffixOverrides=",">
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="url != null and url != ''">
url = #{url},
</if>
<if test="categoryId != null and categoryId != ''">
category_id = #{categoryId},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="updatedTime != null">
updated_time = #{updatedTime},
</if>
</trim>
<where>
<if test="id != null and id != ''">
id = #{id}
</if>
</where>
</update>
service层
@Override
public void saveResource(Resource resource) {
// 补全信息
Date date = new Date();
resource.setCreatedTime(date);
resource.setUpdatedTime(date);
resource.setCreatedBy("system");
resource.setUpdatedBy("system");
resourceMapper.saveResource(resource);
}
@Override
public void updateResource(Resource resource) {
Date date = new Date();
resource.setUpdatedTime(date);
resourceMapper.updateResource(resource);
}
web层
@RequestMapping("/saveOrUpdateResource")
public ResponseResult saveOrUpdateResource(@RequestBody Resource resource){
if(resource.getId()== null){
resourceService.saveResource(resource);
return new ResponseResult(true, 200, "添加资源信息成功", null);
}else{
resourceService.updateResource(resource);
return new ResponseResult(true, 200, "更新资源信息成功", null);
}
}
postman测试
4.4.4、删除资源信息
-
名称: deleteResource
-
描述: 删除角色
-
URL: http://localhost:8080/ssm-web/resource/deleteResource?id=5
-
请求方式: GET
-
请求示例
http://localhost:8080/ssm-web/resource/deleteResource?id=5
响应参数:
参数名称 | 参数说明 | 类型 | schema |
---|---|---|---|
success | boolean | ||
state | integer(int32) | integer(int32) | |
message | string | ||
content | object |
dao层
<delete id="deleteResource" parameterType="Integer">
delete from resource where id = #{id}
</delete>
service层
@Override
public void deleteResource(Integer id) {
resourceMapper.deleteResource(id);
}
web层
@RequestMapping("/deleteResource")
public ResponseResult deleteResource(Integer id){
resourceService.deleteResource(id);
return new ResponseResult(true, 200, "删除资源成功", null);
}
postman测试
5、登录授权
5.1、用户登录
- 名称: login
- 描述: 用户登录
- URL: http://localhost:8080/ssm-web/user/login
- 请求方式: GET
- 请求示例
http://localhost:8080/ssm-web/user/login?phone=18512341234&password=123456
- 响应结果示例
{
state: 1,
message: "success",
content: '{
"access_token": "",
"user_id": "100030016"
}',
success: true
}
dao层
<select id="login" parameterType="user" resultType="user">
select * from user where phone = #{phone}
</select>
service层
@Override
public User login(User user) throws Exception {
User login = userMapper.login(user);
if(login != null && Md5.verify(user.getPassword(), "lagou", user.getPassword())){
return user;
}else{
return null;
}
}
web层
/*用户登录*/
@RequestMapping("/login")
public ResponseResult login(User user, HttpServletRequest request) throws Exception {
User login = userService.login(user);
ResponseResult result = null;
if(login != null){
// 保存access_token
Map<String, Object> map = new HashMap<>();
String access_token = UUID.randomUUID().toString();
map.put("access_token", access_token);
map.put("user_id", login.getId());
HttpSession session = request.getSession();
session.setAttribute("user_id", login.getId());
session.setAttribute("access_token", access_token);
result = new ResponseResult(true, 1, "响应成功", map);
}else{
result = new ResponseResult(true, 1, "用户名密码错误", null);
}
return result;
}
5.2、分配角色(回显)
- 名称: findUserRoleById
- 描述: 获取用户拥有的菜单权限
- URL: http://localhost:8080/ssm-web/user/findUserRoleById
- 请求方式: GET
- 请求示例
http://localhost:8080/ssm-web/user/findUserRoleById?id=4
- 响应结果
参数名称 | 参数说明 | 类型 | 备注 |
---|---|---|---|
success | boolean | ||
state | integer(int32) | ||
message | string | ||
content | object |
- 响应结果示例
{
"success": true,
"state": 200,
"message": "分配角色成功",
"content": [{
"id": 2,
"code": "AUTHORITY_MANAGER",
"name": "权限管理员",
"description": "管理权限相关数据,如角色、菜单、资源。可以给用户分配角色。",
"createdTime": null,
"updatedTime": null,
"createdBy": null,
"updatedBy": null
},
{
"id": 3,
"code": "COURSE_MANAGER",
"name": "课程管理员",
"description": "管理课程信息,对课程、课时、章节进行管理。",
"createdTime": null,
"updatedTime": null,
"createdBy": null,
"updatedBy": null
}]
}
dao层
<select id="findUserRelationRoleById" resultType="role" parameterType="int">
SELECT
r.id,
r.code,
r.name,
r.description
FROM roles r INNER JOIN user_role_relation ur
ON r.`id` = ur.`role_id` INNER JOIN USER u ON ur.`user_id` = u.`id`
WHERE u.`id` = #{id}
</select>
service层
@Override
public List<Role> findUserRelationRoleById(Integer id) {
return userMapper.findUserRelationRoleById(id);
}
web层
@RequestMapping("/findUserRoleById")
public ResponseResult findUserRoleById(Integer id){
List<Role> userRelationRoleById = userService.findUserRelationRoleById(id);
return new ResponseResult(true, 200, "分配角色回显成功", userRelationRoleById);
}
postman测试
5.3、分配角色
- 名称: userContextRole
- 描述: 获取用户拥有的菜单权限
- URL: http://localhost:8080/ssm-web/user/userContextRole
- 请求方式: POST
- 请求示例
{
"userId": 4,
"roleIdList": [4,5,6]
}
- 响应结果
参数名称 | 参数说明 | 类型 | 备注 |
---|---|---|---|
success | boolean | ||
state | integer(int32) | ||
message | string | ||
content | object |
dao层
<delete id="deleteUserContextRole" parameterType="int">
delete from user_role_relation where user_id = #{userId}
</delete>
<insert id="userContextRole" parameterType="user_role_relation">
insert into user_role_relation values(null, #{userId}, #{roleId}, #{createdTime},
#{updatedTime}, #{createdBy}, #{updatedby})
</insert>
service层
@Override
public List<Role> findUserRelationRoleById(Integer id) {
return userMapper.findUserRelationRoleById(id);
}
@Override
public void userContextRole(UserVo userVo) {
// 根据用户id清空中间表的关联关系
userMapper.deleteUserContextRole(userVo.getUserId());
// 想中间表添加记录
for (Integer integer : userVo.getRoleIdList()) {
User_Role_relation userRoleRelation = new User_Role_relation();
userRoleRelation.setUserId(userVo.getUserId());
userRoleRelation.setRoleId(integer);
Date date = new Date();
userRoleRelation.setCreatedTime(date);
userRoleRelation.setUpdatedTime(date);
userRoleRelation.setCreatedBy("system");
userRoleRelation.setUpdatedby("system");
userMapper.userContextRole(userRoleRelation);
}
}
web层
@RequestMapping("/userContextRole")
public ResponseResult userContextRole(@RequestBody UserVo userVo){
userService.userContextRole(userVo);
return new ResponseResult(true, 200, "分配角色成功", null);
}
postman测试
5.4、获取用户拥有的权限
-
名称: getUserPermissions
-
描述: 获取用户拥有的菜单权限
-
URL: http://localhost:8080/ssm-web/user/getUserPermissions
-
请求方式: GET
-
请求示例
-
响应结果
参数名称 | 参数说明 | 类型 | 备注 |
---|---|---|---|
success | boolean | ||
state | integer(int32) | ||
message | string | ||
content | object |
- 响应结果示例
{
"state": 1,
"message": "success",
"content": {
"menuList": [{
"id": 1,
"parentId": -1,
"name": "权限管理",
"subMenuList": [{
"id": 2,
"name": "角色列表"
},
{
"id": 3,
"name": "菜单列表",
}]
}],
"resourceList": [{
"id": 1,
"name": "获取所有角色"
},
{
"id": 2,
"name": "给用户分配角色",
}]
},
"success": true
}
dao层
<select id="findParentMenuByRoleId" parameterType="java.util.List"
resultType="Menu">
SELECT
DISTINCT m.*
FROM roles r INNER JOIN role_menu_relation rm ON r.`id` = rm.role_id
INNER JOIN menu m ON rm.menu_id = m.id
WHERE m.parent_id = -1 AND r.id IN
<foreach collection="list" item="item" open="(" separator=","
close=")">
#{item}
</foreach>
GROUP BY m.id
</select>
<select id="findSubMenuByPid" resultType="Menu">
select * from menu where parent_id = #{pid}
</select>
<select id="findResourceByRoleId" parameterType="java.util.List"
resultType="Resource">
SELECT
DISTINCT rc.*
FROM roles r INNER JOIN role_resource_relation rrr ON r.`id` =
rrr.`role_id`
INNER JOIN resource rc ON rrr.`resource_id` = rc.`id` WHERE r.id IN
<foreach item="item" index="index" collection="list" open="("
separator="," close=")">
#{item}
</foreach>
GROUP BY rc.id;
</select>
service层
@Override
public ResponseResult getUserPermissions(Integer id) {
//1.获取当前用户拥有的角色
List<Role> roleList = userMapper.findUserRelationRoleById(id);
//2.获取角色ID,保存到 list
List<Integer> list = new ArrayList<>();
for (Role role : roleList) {
list.add(role.getId());
}
//3.根据角色id查询 父菜单
List<Menu> parentMenu = userMapper.findParentMenuByRoleId(list);
//4.封装父菜单下的子菜单
for (Menu menu : parentMenu) {
List<Menu> subMenu = userMapper.findSubMenuByPid(menu.getId());
menu.setSubMenuList(subMenu);
}
//5.获取资源权限
List<Resource> resourceList = userMapper.findResourceByRoleId(list);
//6.封装数据
Map<String,Object> map = new HashMap<>();
map.put("menuList",parentMenu); //menuList: 菜单权限数据
map.put("resourceList",resourceList);//resourceList: 资源权限数据
ResponseResult result = new ResponseResult(true,200,"响应成功",map);
return result;
}
web层
/**
* 获取用户权限
* */
@RequestMapping("/getUserPermissions")
public ResponseResult getUserPermissions(HttpServletRequest request){
//获取请求头中的 token
String token = request.getHeader("Authorization");
//获取session中的access_token
HttpSession session = request.getSession();
String access_token = (String)session.getAttribute("access_token");
//判断
if(token.equals(access_token)){
int user_id = (Integer)session.getAttribute("user_id");
ResponseResult result = userService.getUserPermissions(user_id);
return result;
}else{
ResponseResult result = new ResponseResult(false,400,"获取失败","");
return result;
}
}
postman测试