谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity

文章目录

    • 一、权限管理需求描述
      • 1、菜单管理
      • 2、角色管理
      • 3、用户管理
      • 4、表与表之间的关系
    • 二、spring security介绍
      • 1、框架介绍
      • 2、认证与授权实现思路
    • 三、整合spring security
      • 1、复制工具类到common_utils
      • 2、在common下创建spring_security模块
      • 3、在spring_security引入相关依赖
      • 4、代码结构说明
      • 5、对springsecurity具体说明
    • 四、开发权限管理接口 -- 后端
      • 1、在service模块下创建子模块service-acl
      • 2、创建权限管理相关的表
      • 3、复制权限管理接口代码
      • 4、在service_acl模块中引入依赖
      • 5、编写application.properties配置文件
      • 6、开发权限管理接口
        • (1)查询所有菜单
        • (2)递归删除菜单
        • (3)给角色分配权限
    • 五、权限管理 -- 前端
      • 1、到源码中找到整合前端代码,替换项目中前端项目内容
      • 2、在前端项目中下载依赖
      • 3、需要修改两个地方
      • 4、修改config/dev.env.js地址
      • 5、测试功能
      • 6、权限整合是spring security执行过程


一、权限管理需求描述

不同角色的用户登录后台管理系统拥有不同的菜单权限与功能权限,权限管理包含三个功能模块:菜单管理、角色管理和用户管理

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第1张图片

1、菜单管理

(1)菜单列表:使用树形结构显示菜单列表
(2)添加菜单:点击添加菜单,弹框进行添加
(3)修改菜单
(4)删除菜单

2、角色管理

(1)角色列表:实现角色的条件查询带分页功能
(2)角色添加
(3)角色修改
(4)角色删除

  • 普通删除
  • 批量删除

(5)角色分配菜单

3、用户管理

(1)用户列表
(2)用户添加
(3)用户修改
(4)用户删除
(5)用户分配角色

4、表与表之间的关系

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第2张图片

二、spring security介绍

1、框架介绍

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。

(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。

(2)用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

Spring Security其实就是用filter,多请求的路径进行过滤。

(1)如果是基于Session,那么Spring-security会对cookie里的sessionid进行解析,找到服务器存储的sesion信息,然后判断当前用户是否符合请求的要求。

(2)如果是token,则是解析出token,然后将当前请求加入到Spring-security管理的权限信息中去

2、认证与授权实现思路

如果系统的模块众多,每个模块都需要就行授权与认证,所以我们选择基于token的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为key,权限列表为value的形式存入redis缓存中,根据用户名相关信息生成token返回,浏览器将token记录到cookie中,每次调用api接口都默认将token携带到header请求头中,Spring-security解析header头获取token信息,解析token获取当前用户名,根据用户名就可以从redis中获取权限列表,这样Spring-security就能够判断当前请求是否有权限访问

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第3张图片

三、整合spring security

1、复制工具类到common_utils

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第4张图片

2、在common下创建spring_security模块

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第5张图片

3、在spring_security引入相关依赖

<dependencies>
    <dependency>
        <groupId>com.kuanggroupId>
        <artifactId>common_utilsartifactId>
        <version>0.0.1-SNAPSHOTversion>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-securityartifactId>
    dependency>

    <dependency>
        <groupId>io.jsonwebtokengroupId>
        <artifactId>jjwtartifactId>
    dependency>
dependencies>

4、代码结构说明

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第6张图片

5、对springsecurity具体说明

SpringSecurity 微服务对权限的整合:https://blog.csdn.net/weixin_45606067/article/details/111742560

四、开发权限管理接口 – 后端

1、在service模块下创建子模块service-acl

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第7张图片

2、创建权限管理相关的表

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第8张图片

3、复制权限管理接口代码

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第9张图片

4、在service_acl模块中引入依赖

这里我们整合了spring security 模块

<dependencies>
    <dependency>
        <groupId>com.kuanggroupId>
        <artifactId>spring_securityartifactId>
        <version>0.0.1-SNAPSHOTversion>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
    dependency>
dependencies>

5、编写application.properties配置文件

# 服务端口
server.port=8009
# 服务名
spring.application.name=service-acl

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

spring.redis.host=127.0.0.1
ing.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000

spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
#最小空闲

#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/kuang/aclservice/mapper/xml/*.xml

# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

6、开发权限管理接口

(1)查询所有菜单

PermissionController类

@ApiOperation(value = "查询所有菜单")
@GetMapping
public R indexAllPermission() {
   List<Permission> list =  permissionService.queryAllMenu();
   return R.ok().data("children",list);
}

PermissionServiceImpl 类

//获取全部菜单
@Override
public List<Permission> queryAllMenu() {
    //根据id排序
    QueryWrapper<Permission> wrapper = new QueryWrapper<>();
    wrapper.orderByDesc("id");

    //查询菜单所有数据
    List<Permission> permissionList = baseMapper.selectList(wrapper);

    //把查询所有菜单list集合按要求进行封装
    List<Permission> result = bulidPermission(permissionList);
    return result;
}

//使用递归方法建菜单
//把返回所有菜单list集合进行封装的方法
public static List<Permission> bulidPermission(List<Permission> permissionList) {
    //创建list集合,用于数据最终封装
    List<Permission> finalNode = new ArrayList<>();
    //把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
    for(Permission permissionNode : permissionList) {
        //得到顶层菜单 pid=0菜单
        if("0".equals(permissionNode.getPid())) {
            //设置顶层菜单的level是1
            permissionNode.setLevel(1);
            //根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
            finalNode.add(selectChildren(permissionNode,permissionList));//permissionNode一级菜单,permissionList所有菜单
        }
    }
    return finalNode;//最终菜单
}

//递归查找子节点
private static Permission selectChildren(Permission permissionNode, List<Permission> permissionList) {
   //1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
   permissionNode.setChildren(new ArrayList<Permission>());

   //2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
   for(Permission it : permissionList) {
       //判断 id和pid值是否相同
       if(permissionNode.getId().equals(it.getPid())) {
           //把父菜单的level值+1
           int level = permissionNode.getLevel()+1;
           it.setLevel(level);
           //如果children为空,进行初始化操作
           if(permissionNode.getChildren() == null) {
               permissionNode.setChildren(new ArrayList<Permission>());
           }
           //把查询出来的子菜单放到父菜单里面
           permissionNode.getChildren().add(selectChildren(it,permissionList));
       }
   }
   return permissionNode;
}

Permission实体类添加的属性

@ApiModelProperty(value = "层级")
@TableField(exist = false)
private Integer level;

@ApiModelProperty(value = "下级")
@TableField(exist = false)
private List<Permission> children;

@ApiModelProperty(value = "是否选中")
@TableField(exist = false)
private boolean isSelect;

(2)递归删除菜单

PermissionController 类

@ApiOperation(value = "递归删除菜单")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {
    permissionService.removeChildById(id);
    return R.ok();
}

PermissionServiceImpl 类

//递归删除菜单
@Override
public void removeChildById(String id) {
    //1 创建list集合,用于封装所有删除菜单id值
    List<String> idList = new ArrayList<>();
    //2 向idList集合设置删除菜单id
    this.selectPermissionChildById(id, idList);

    //把当前id封装到list里面
    idList.add(id);
    baseMapper.deleteBatchIds(idList);
}

//2 根据当前菜单id,查询菜单里面子菜单id,封装到list集合
private void selectPermissionChildById(String id, List<String> idList) {
   //查询菜单里面子菜单id
   QueryWrapper<Permission>  wrapper = new QueryWrapper<>();
   wrapper.eq("pid",id);
   wrapper.select("id");
   List<Permission> childIdList = baseMapper.selectList(wrapper);

   //把childIdList里面菜单id值获取出来,封装idList里面,做递归查询
   childIdList.stream().forEach(item -> {
       //封装idList里面
       idList.add(item.getId());
       //递归查询
       this.selectPermissionChildById(item.getId(),idList);
   });
}

(3)给角色分配权限

PermissionController 类

@ApiOperation(value = "给角色分配权限")
@PostMapping("/doAssign")
public R doAssign(String roleId,String[] permissionId) {
    permissionService.saveRolePermissionRealtionShip(roleId,permissionId);
    return R.ok();
}

PermissionServiceImpl 类

//给角色分配权限
@Override
public void saveRolePermissionRealtionShip(String roleId, String[] permissionIds) {

    rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));

    List<RolePermission> rolePermissionList = new ArrayList<>();
    for(String permissionId : permissionIds) {
        if(StringUtils.isEmpty(permissionId)) continue;
  
        RolePermission rolePermission = new RolePermission();
        rolePermission.setRoleId(roleId);
        rolePermission.setPermissionId(permissionId);
        rolePermissionList.add(rolePermission);
    }
    rolePermissionService.saveBatch(rolePermissionList);
}

这里我们只写了比较重要的代码,还有一些看我后面上传的代码中有。

五、权限管理 – 前端

1、到源码中找到整合前端代码,替换项目中前端项目内容

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第10张图片

2、在前端项目中下载依赖

npm install --save vuex-persistedstate

3、需要修改两个地方

(1)修改router文件夹里面index.js里面路径和vue文件地址

在这里插入图片描述

(2)修改数据库菜单路径和页面地址

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第11张图片

4、修改config/dev.env.js地址

端口号改为网关的地址

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第12张图片

5、测试功能

启动redis和nacos

6、权限整合是spring security执行过程

谷粒学院(二十二)spring security | 权限管理 | 权限整合springsecurity_第13张图片


如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

你可能感兴趣的:(谷粒学院,/,权限管理系统,谷粒学院,spring,security,权限管理,整合权限)