SpringBoot整合JWT+Spring Security+Redis实现登录拦截(二)权限认证

上篇博文中我们已经实现了登录拦截,接下来我们继续补充代码,实现权限的认证

一、RBAC权限模型

        什么事RBAC权限模型?

        RBAC权限模型(Role-Based Access Control)即:基于角色的权限访问控制。在RBAC中,权限与角色关联,用户通过赋予角色而获得相应角色的权限。故我们需要如下几张表:

        用户表:系统接口及访问的操作者

        权限表:能够访问某接口或者做某操作的授权资格

        角色表:具有一类相同操作权限的用户的总称

        用户角色表:用户角色相关联的表

        角色权限表:角色与权限相关联的表

二、创建对应的数据库表

        可根据项目需要增加或删减、修改对应的表字段

        sys_user

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',`nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',`user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',`gender` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',`phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号码',`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色ID',`is_admin` bit(1) NULL DEFAULT b'0' COMMENT '是否为admin账号',`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',`enabled` bit(1) NULL DEFAULT NULL COMMENT '是否启用',`create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',`update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统用户' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

 sys_role

DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称',`level` int(0) NULL DEFAULT NULL COMMENT '角色级别',`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',`create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',`update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色表' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

sys_menu

DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu`  (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',`pid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上级菜单ID',`sub_count` int(0) NULL DEFAULT 0 COMMENT '子菜单数目',`type` int(0) NULL DEFAULT NULL COMMENT '菜单类型',`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单标题',`menu_sort` int(0) NULL DEFAULT NULL COMMENT '排序',`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图标',`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '链接地址',`cache` bit(1) NULL DEFAULT b'0' COMMENT '缓存',`hidden` bit(1) NULL DEFAULT b'0' COMMENT '隐藏',`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限',`create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',`update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 118 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统菜单' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

sys_user_role

DROP TABLE IF EXISTS `sys_users_roles`;
CREATE TABLE `sys_users_roles`  (`user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户ID',`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色ID',PRIMARY KEY (`user_id`, `role_id`) USING BTREE,INDEX `user_id`(`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户角色关联' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

sys_role_menu

DROP TABLE IF EXISTS `sys_roles_menus`;
CREATE TABLE `sys_roles_menus`  (`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色ID',`menu_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单ID',PRIMARY KEY (`role_id`, `menu_id`) USING BTREE,INDEX `FKcngg2qadojhi3a651a5adkvbq`(`role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色菜单关联' ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;

三、生成5张基础表对应的Java代码

        可自行书写或使用mybatis工具进行生成,也可参考之前的博文

mybatis-plus自动生成代码(整理版)_mybatisplus代码自动生成-CSDN博客文章浏览阅读111次。整理版,添加了注释模版,常用基础方法。也可直接替换成公共的或自己代码中自定义的。仅提供基础方法,可根据具体需求自行改造。仅提供基础方法,可根据具体需求自行改造。仅提供基础方法,可根据具体需求自行改造。_mybatisplus代码自动生成https://blog.csdn.net/shaogaiyue9745602/article/details/134525030?spm=1001.2014.3001.5502

四、鉴权实现

  1.创建PermissionMapper.xml

           变现sql根据用户ID查询角色对应的权限

<?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.hng.mapper.PermissionMapper"><select id="selectPermsByUserId" resultType="java.lang.String">SELECTDISTINCT m.permissionFROMsys_users_roles urLEFT JOIN sys_role r ON ur.role_id = r.idLEFT JOIN sys_roles_menus	rm ON ur.role_id = rm.role_idLEFT JOIN sys_menu m ON m.id = rm.menu_idWHEREuser_id = #{userId}</select>
</mapper>

2.创建PermissionMapper

package com.hng.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hng.entity.SysMenu;import java.util.List;/*** <p>* 系统菜单 Mapper 接口* </p>** @author 郝南过* @since 2023-12-19*/
public interface PermissionMapper extends BaseMapper<SysMenu> {List<String> selectPermsByUserId(String userId);
}

3.改造SecurityUser

    (1)改造构造函数增加权限集合

    private List<String> permissions;public SecurityUser(SysUser user, List<String> permissions) {this.user = user;this.permissions = permissions;}

    (2)改造getAuthorities

    @Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {//将permissions中的String类型的权限信息封装成SimpleGrantedAuthority对象if(authorities!=null){return authorities;}authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());return authorities;}

 4.改造UserDetailsServiceImpl

        修改loadUserByUsername方法,使用Permission增加权限查询

package com.hng.config.security;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hng.config.exception.customize.EntityNotFoundException;
import com.hng.modules.system.entity.SysUser;
import com.hng.modules.system.mapper.PermissionMapper;
import com.hng.modules.system.mapper.SysMenuMapper;
import com.hng.modules.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;/*** @Author: 郝南过* @Description: 将Security拦截的用户名密码改为数据库中已有的用户名密码,Security自己校验密码,默认使用PasswordEncoder,格式为{id}password(id代表加密方式),* 一般不采用此方式,SpringSecurity提供了BcryptPasswordEncoder,只需将此注入到spring容器中。SpringSecurity就会使用它进行替换校验* @Date: 2023/12/11 11:29* @Version: 1.0*/
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {@Resourceprivate SysUserService sysUserService;@Resourceprivate PermissionMapper permissionMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//查询用户信息LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper();queryWrapper.eq(SysUser::getUserName,username);SysUser user = sysUserService.getOne(queryWrapper);if(Objects.isNull(user)){throw new RuntimeException("用户名或密码错误");}//查询授权信息List<String> permissions = permissionMapper.selectPermsByUserId(user.getId());//判断用户是否是管理员,如果是管理员添加admin权限if(user.getIsAdmin()){permissions.add("admin");}return new SecurityUser(user,permissions);}
}

5.自定义权限检测

      可直接使用已有的权限检测@PreAuthorize(“hasAuthority('自定义字符串')”),hasAuthority是系统提供的,可直接使用,也可以自定义。以下为自定义,为方便直接判断admin用户,并给admin用户授予所有权限。

PermissionConfig
package com.hng.config.security;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;/*** 自定义权限检测*/
@Component(value = "ex")
public class PermissionConfig {public Boolean check(String... permissions) {// 获取当前用户的所有权限Authentication authentication = SecurityContextHolder.getContext().getAuthentication();SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();List<String> exPermissions = securityUser.getPermissions();// 判断当前用户的所有权限是否包含接口上定义的权限return exPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(exPermissions::contains);}
}

6.在SecurityConfig中添加注解

@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限权限认证

7.在Cotroller中添加对应的权限字符

        如果未自定义权限检测使用注解@PreAuthorize(“hasAuthority('自定义字符串')”),本篇博文中的例子已经自定义为@PreAuthorize("@ex.check('自定义字符串')")

  SysUserController 示例

package com.hng.controller;import lombok.RequiredArgsConstructor;
import io.swagger.annotations.ApiOperation;
import com.hng.config.response.ResponseResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import io.swagger.annotations.ApiParam;import com.hng.entity.SysUser;
import com.hng.service.SysUserService;/*** <p>* 系统用户 前端控制器* </p>*/
@Slf4j
@Api(value = "SysUser", tags = "SysUser")
@RestController
@RequiredArgsConstructor //Lombok的一个注解,简化@Autowired
@RequestMapping("/sys-user")
public class SysUserController {private final SysUserService sysUserService;@PostMapping("/getList")@ApiOperation("sysUser列表查询")@PreAuthorize("@ex.check('SysUser:list')")public ResponseResult queryAllSysUser(@Validated @RequestBody SysUser sysUser){List<SysUser> list = sysUserService.queryAll(sysUser);return ResponseResult.success(list);}@PostMapping("/add")@ApiOperation("新增SysUser")@PreAuthorize("@ex.check('SysUser:add')")public ResponseResult addSysUser(@Validated @RequestBody SysUser sysUser){sysUserService.addSysUser(sysUser);return ResponseResult.success();}/*** 根据ID查询数据* @param id ID*/@GetMapping("getById/{id}")@ApiOperation("sysUser根据Id查询")@ResponseBody@PreAuthorize("@ex.check('SysUser:getById')")public ResponseResult getById(@PathVariable Integer id) {return ResponseResult.success(sysUserService.getSysUserById(id));}/*** 更新数据* @param sysUser 实体对象*/@PutMapping("update")@ApiOperation("sysUser更新")@ResponseBody@PreAuthorize("@ex.check('SysUser:edit')")public ResponseResult update(@Validated @RequestBody SysUser sysUser) {sysUserService.updateSysUser(sysUser);return ResponseResult.success();}/*** 删除数据* @param id ID*/@DeleteMapping("delete/{id}")@ApiOperation("sysUser根据Id删除")@ResponseBody@PreAuthorize("@ex.check('SysUser:del')")public ResponseResult delete(@PathVariable Integer id) {sysUserService.deleteSysUser(id);return ResponseResult.success();}}

五.数据库中添加数据

        根据自己定义的权限字符串与用户进行数据添加

六.测试

        使用pomstman进行测试,注此时可以测试上篇博文中的权限认证异常处理器

 【demo示例代码】

https://download.csdn.net/download/shaogaiyue9745602/88661442icon-default.png?t=N7T8https://download.csdn.net/download/shaogaiyue9745602/88661442

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/300710.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分别使用OVP-UVP和OFP-UFP算法以及AFD检测算法实现反孤岛检测simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 OVP-UVP算法 4.2 OFP-UFP算法 4.3 AFD检测算法 5.完整工程文件 1.课题概述 分别使用OVP-UVP和OFP-UFP算法以及AFD检测算法实现反孤岛检测simulink建模与仿真。 2.系统仿真结果 3.核心程序与模型…

金和OA C6 gethomeinfo sql注入漏洞

产品介绍 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 漏洞概述 金和 OA C6 gethomeinfo接口处存在SQL注入漏洞&#xff0c;攻击者除了可以利用 SQL 注入漏洞获取…

顺序表的基本操作(必学)

目录 线性表&#xff1a; 顺序表&#xff1a; 概念和结构&#xff1a; 动态顺序表常用操作实现&#xff1a; 头文件&#xff08;数组顺序表的声明&#xff09;&#xff1a; 各种基本操作总的声明&#xff1a; 顺序表的初始化&#xff1a; 顺序表的销毁 顺序表的打印 …

【中小型企业网络实战案例 二】配置网络互连互通

​【中小型企业网络实战案例 一】规划、需求和基本配置-CSDN博客 热门IT技术视频教程&#xff1a;https://xmws-it.blog.csdn.net/article/details/134398330?spm1001.2014.3001.5502 配置接入层交换机 1.以接入交换机ACC1为例&#xff0c;创建ACC1的业务VLAN 10和20。 <…

因吹斯汀!只需上传照片,GPT-4V精准识别食物的卡路里和摄入热量

健身和减肥的朋友有福啦&#xff01; 最近一篇文章探索了GPT-4V在膳食评估领域的强大能力&#xff0c;可以根据饮食图片精准判断食物的种类与重量&#xff0c;并给出营养成分的分析&#xff0c;包括碳水化合物、蛋白质、脂肪占比。 最最重要的是&#xff0c;它还能告诉我们这…

c语言的初始学习(练习)

##初学c语言---MOOC浙江大学翁恺先生学习c语言 那么我们先看看这个题目吧&#xff0c;这是初始语法的应用。 记住&#xff0c;我们的程序是按步骤执行的&#xff0c;并不是在不同的两行同时进行。 程序设计&#xff1a;1.了解题目的需要&#xff0c;几个变量需要用到&#x…

App应用如何在应用市场获得更多下载量?

App的转化率至关重要&#xff0c;App如何获得更多用户&#xff0c;提高应用的下载量&#xff1f; 据 Apple 称&#xff0c;每周有 6.5亿访问者访问应用商店&#xff0c;77%的应用下载来自 iOS 应用商店的自然搜索。随着 Apple 默认关闭了IDFA&#xff0c;自然搜索比以往任何时…

众和策略:12月新批国产网游版号数量过百

上星期五&#xff08;22日&#xff09;&#xff0c;A股冲高回落&#xff0c;三大股指挨近午盘拉升走高&#xff0c;午后再度回落走低&#xff0c;沪指尾盘跌幅收窄。到收盘&#xff0c;沪指跌0.13%报2914.78点&#xff0c;深成指跌0.39%报9221.31点&#xff0c;创业板指跌0.37%…

怎么判断台灯是否护眼?分享适合考研使用的护眼台灯

虽然台灯是家家户户都会有的一盏照明设备&#xff0c;但是很多人并不是了解自家台灯是好是坏&#xff0c;能不能护眼等等。其实台灯是非常有讲究的&#xff0c;如果长期使用一些不合格、劣质的台灯&#xff0c;会让我们在不知不觉中造成视力损伤&#xff0c;从而导致近视。 也…

【软考中级】网络工程师:8.网络安全

本章考察内容比较广泛&#xff0c;考题对知识点都会有所涉及。 8.1 网络安全的基本概念 8.1.1 网络安全威胁的类型 窃听 这种情况发生在广播式网络系统中&#xff0c;每个节点都可以读取数据&#xff0c;实现搭线窃听、安装通信监视器和读取网上的信息等。 假冒 当一个实体…

AIGC重塑教育:AI大模型驱动的教育变革与实践

目录 引言 AI与教育工作者 ​教育资源不平衡 引言 AI正迅猛地改变着我们的生活。 根据高盛发布的一份报告&#xff0c;AI有可能取代3亿个全职工作岗位&#xff0c;影响全球18%的工作岗位。在欧美&#xff0c;或许四分之一的工作可以用AI完成。另一份Statista的报告预测&…

百度Apollo五步入门自动驾驶:Dreamview与离线数据包分析(文末赠送apollo周边)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 粉丝福利活动 ✅参与方式&#xff1a;通过连接报名观看课程&#xff0c;即可免费获取精美周边 ⛳️活动链接&#xf…