SpringBoot整合SpringSecurity实现权限控制(七):权限分配

本文详细介绍了如何在SpringBoot项目中整合SpringSecurity实现权限控制的权限分配功能,包括后端创建权限表、实现角色权限分配服务和接口,以及前端添加角色权限API、角色分配页面和动态生成菜单栏的逻辑。通过用户、角色和菜单的关联,实现精细化的权限管理。
摘要由CSDN通过智能技术生成

系列文章目录
《SpringBoot整合SpringSecurity实现权限控制(一):实现原理》
《SpringBoot整合SpringSecurity实现权限控制(二):权限数据基本模型设计》
《SpringBoot整合SpringSecurity实现权限控制(三):前端动态装载路由与菜单》
《SpringBoot整合SpringSecurity实现权限控制(四):角色管理》
《SpringBoot整合SpringSecurity实现权限控制(五):用户管理》
《SpringBoot整合SpringSecurity实现权限控制(六):菜单管理》


一、实现原理

  • 在前面的系列文章中,我们已经实现了用户管理、角色管理与菜单管理,接下来我们把这三个功能串起来:
  1. 通过权限分配把让角色关联到各个功能菜单。比如让系统管理员角色关联到用户管理、角色管理等菜单。
  2. 通过角色设置让用户关联到单个或多个角色。比如让张三用户关联到系统管理员角色。
  3. 用户关联到角色,角色关联到菜单,也即让用户间接拥有了系统的功能。

在这里插入图片描述

二、后端实现

2.1 创建权限表

  • 该表存储角色id与菜单id的关联信息
/**
 * 权限表
 *
 * @author zhuhuix
 * @date 2021-10-26
 */
@ApiModel(value = "权限信息")
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_permission")
public class SysPermission {
   

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
	// 角色id
    private Long roleId;
	// 菜单id
    private Long menuId;

    private Timestamp createTime;

    public SysPermission(Long roleId, Long menuId, Timestamp createTime) {
   
        this.roleId = roleId;
        this.menuId = menuId;
        this.createTime = createTime;
    }
}

2.2 添加操作权限表的Mapper接口

  • 通过继承mybatis-plus的BaseMapper接口创建操作权限表的DAO接口,该BaseMapper接口已经包含了基本的增删改查操作。
/**
 * 权限表DAO接口
 *
 * @author zhuhuix
 * @date 2021-10-26
 */
@Mapper
public interface SysPermissionMapper extends BaseMapper<SysPermission> {
   

 // BaseMapper接口已经默认实现了基本的增删改查操作
}

2.3 实现角色权限分配的服务

  • 在原有角色管理的服务接口中加入获取角色权限与保存角色权限的接口.
/**
 * 角色信息接口
 *
 * @author zhuhuix
 * @date 2021-09-13
 * @date 2021-10-26 增加getPermission,savePermission
 */
public interface SysRoleService {
   

    ....

    /**
     * 获取角色权限
     *
     * @param roleId 角色id
     * @return 角色权限列表
     */
    List<SysPermission> getPermission(Long roleId);

    /**
     * 保存角色权限
     *
     * @param roleId 角色id
     * @param menus 权限表
     * @return 是否成功
     */
    Boolean savePermission(Long roleId,Set<Long> menus);

}
  • 实现获取角色权限与保存角色权限的接口
/**
 * 角色实现类
 *
 * @author zhuhuix
 * @date 2021-09-13
 * @date 2021-10-26 实现getPermission,savePermission接口
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysRoleServiceImpl implements SysRoleService {
   

    private final SysRoleMapper sysRoleMapper;
    private final SysPermissionMapper sysPermissionMapper;

    ...
    
    @Override
    public List<SysPermission> getPermission(Long roleId) {
   
        QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysPermission::getRoleId, roleId);
        return sysPermissionMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean savePermission(Long roleId, Set<Long> menus) {
   
        // 先根据roleId删除原有权限
        QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysPermission::getRoleId, roleId);
        sysPermissionMapper.delete(queryWrapper);
        // 再插入roleId新权限
        for (Long menu : menus) {
   
            int rowCount = sysPermissionMapper.insert(
                    new SysPermission(roleId, menu, Timestamp.valueOf(LocalDateTime.now())));
            if (rowCount <= 0) {
   
                throw new RuntimeException("保存权限失败");
            }
        }

        return true;
    }
}

2.4 在Controller层添加访问API接口

在这里插入图片描述

/**
 * 角色信息api
 *
 * @author zhuhuix
 * @date 2021-09-13
 * @date 2021-10-26 增加getPermission,savePermission API接口
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/api/role")
@Api(tags = "角色信息接口")
public class SysRoleController {
   

    private final SysRoleService sysRoleService;

    ....

    @ApiOperation("获取角色权限信息")
    @GetMapping("{roleId}/permission")
    public ResponseEntity<Object> getPermission(@PathVariable Long roleId) {
   
        return ResponseEntity.ok(sysRoleService.getPermission(roleId));
    }

    @ApiOperation("保存角色权限信息")
    @PostMapping("{roleId}/permission")
    public ResponseEntity<Object> savePermission(@PathVariable Long roleId,@RequestBody Set<Long> menus) {
   
        return ResponseEntity.ok(sysRoleService.savePermission(roleId,menus));
    }
}

三、前端实现

3.1 添加角色权限api访问接口

  • 根据后端API,在角色信息api访问中添加读取权限与保存权限的接口
/**
 * 角色访问后端api
 * 2021-10-26 添加getPermission,savePermission
 */
import request from '@/utils/request'

...

export function getPermission(roleId) {
   
  return request({
   
    url: '/api/role/' + roleId + '/permission',
    method: 'get'
  })
}

export function savePermission(roleId, data) {
   
  return request({
   
    url: '/api/role/' + roleId + '/permission',
    method: 'post',
    data
  })
}

3.2 添加角色分配权限的页面

  1. 我们需要在原有角色信息的卡片列表中增加分配权限的按钮,用户点击按钮后弹出对应角色分配权限的操作页面。
    在这里插入图片描述
  2. 在弹出的操作页面上引用TreeSelect组件,加载系统的功能菜单,供用户选择。
    在这里插入图片描述
  3. 权限分配页面的完整实现代码
/**
* role/index.vue
* 2021-10-27 增加角色权限分配操作页面
*/
<template>
  <div class="app-container">
    <!--工具栏-->
    <div class="head-container">
      <!-- 搜索 -->
      <el-input
        v-model="roleName"
        size="small"
        clearable
        placeholder="输入角色名称搜索"
        style="width: 200px"
        class="filter-item"
        @keyup.enter.native="doQuery"
      />
      <el-date-picker
        v-model="createTime"
        :default-time="['00:00:00', '23:59:59']"
        type="daterange"
        range-separator=":"
        size="small"
        class="date-item"
        value-format="yyyy-MM-dd HH:mm:ss"
        start-placeholder="开始日期"
        end-placeholder="结束日期"
      />
      <el-button
        class="filter-item"
        size="mini"
        type="success"
        icon="el-icon-search"
        @click="doQue
Spring BootSpring Security是一对好朋友,Spring Boot提供了强大的自动配置和快速开发的能力,而Spring Security则提供了完整的安全解决方案,可以实现用户认证、授权、安全过滤等功能。本文将介绍如何在Spring Boot整合Spring Security实现权限控制。 1. 添加Spring Security依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 2. 配置Spring SecuritySpring Boot中,可以通过application.properties或application.yml文件配置Spring Security。以下是一个简单的配置: ``` spring.security.user.name=admin spring.security.user.password=123456 spring.security.user.roles=ADMIN ``` 这个配置定义了一个用户名为admin,密码为123456,角色为ADMIN的用户。在实际应用中,应该将用户名和密码存储在数据库或其他安全存储中。 3. 创建SecurityConfig类 创建一个继承自WebSecurityConfigurerAdapter的SecurityConfig类,并重写configure方法: ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("{noop}123456").roles("ADMIN"); } } ``` configure方法定义了应用程序的安全策略,这里配置了所有请求都需要认证(即登录)才能访问,除了首页和登录页,这两个页面可以匿名访问。formLogin方法配置了自定义的登录页面,logout方法配置了退出登录的操作。 configureGlobal方法定义了一个内存中的用户,用户名为admin,密码为123456,角色为ADMIN。在实际应用中,应该将用户信息存储在数据库或其他安全存储中。 4. 创建登录页面 在templates目录下创建一个名为login.html的登录页面,例如: ``` <!DOCTYPE html> <html> <head> <title>Login Page</title> </head> <body> <h1>Login Page</h1> <div th:if="${param.error}"> Invalid username and password. </div> <div th:if="${param.logout}"> You have been logged out. </div> <form th:action="@{/login}" method="post"> <div> <label>Username:</label> <input type="text" name="username" /> </div> <div> <label>Password:</label> <input type="password" name="password" /> </div> <div> <button type="submit">Login</button> </div> </form> </body> </html> ``` 5. 运行应用程序 在浏览器中访问http://localhost:8080/login,输入用户名admin和密码123456,即可登录成功。如果输入错误的用户名或密码,则会提示“Invalid username and password.”。如果成功登录后再访问http://localhost:8080/home,则可以看到“Welcome home!”的欢迎消息。 6. 实现权限控制 上面的例子中只实现了登录认证,没有实现权限控制。下面介绍如何实现权限控制。 首先需要在configureGlobal方法中添加更多的用户和角色: ``` @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("{noop}123456").roles("ADMIN") .and() .withUser("user").password("{noop}password").roles("USER"); } ``` 这里定义了一个管理员用户和一个普通用户,分别拥有ADMIN和USER两个角色。 然后在configure方法中添加更多的安全策略: ``` @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } ``` 这里添加了一个安全策略,即/admin/**路径需要拥有ADMIN角色才能访问。 现在管理员用户可以访问/admin/**路径,而普通用户则不能访问。如果普通用户尝试访问/admin/**路径,则会提示“Access is denied”。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智慧zhuhuix

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值