springboot 整合 Spring Security 中篇(RBAC权限控制)

1.先了解RBAC 是什么

RBAC(Role-Based Access control) ,也就是基于角色的权限分配解决方案

在这里插入图片描述

2.数据库读取用户信息和授权信息

1.上篇用户名好授权等信息都是从内存读取实际情况都是从数据库获取;

在这里插入图片描述
主要设计两个类
UserDetails和UserDetailsService
看下继承图:
在这里插入图片描述
在这里插入图片描述
不难看出 InMemoryUserDetailsManager 继承UserDetailsService

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.security.core.userdetails;import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();boolean isAccountNonExpired();boolean isAccountNonLocked();boolean isCredentialsNonExpired();boolean isEnabled();
}

不难看出UserDetails 也就是和普通的pojo
综上所述,只需要写一个类实现UserDetailsService 接口的方法和写一个普通的javaBean 继承UserDetails,交给spring 容器也就完成了自定义用户的信息

3.创建5张表(用户表,角色表,权限表,用户角色表,角色权限表)
create table  sys_user (id int auto_increment primary key ,
`name` varchar(50) unique  not null comment '用户名' ,`password` varchar(200) comment '密码',
`is_expired` int default 1 comment '登陆是否过期',
`is_locked` int default  1 comment '账号是否锁定',
`is_enable` int default 1  comment '账号是否可用',
`credentials_expired` int default  1 comment '凭证过期');
select  * from sys_user;

添加两条数据测试 密码都是123456
在这里插入图片描述

create table  sys_roles (id int auto_increment primary key ,`name` varchar(200)  not null comment '角色名称');
create table sys_authority(id int auto_increment primary key ,`authority` varchar(120) not null
);

备注;老师和学生,老师可以删除作业。查看作业。修改作业
学生拥有查看,修改作业
在这里插入图片描述


create table  `sys_user_roles` (`user_id` int not null  comment '用户id',`roles_id` int not null comment '校色id'
);

为用户张三和小李分配角色
张三拥有学生的权限,小李拥有老师权限
在这里插入图片描述

create table  `sys_roles_authority` (id int not null  comment '角色id',`authority_id` int not null comment '权限id'
);

添加两个角色。角色1 学生 角色2 老师
在这里插入图片描述

3.定义一个类实现UserDetailsService交给spring 容器调度

主要在这个方法loadUserByUsername 从数据库读取用户的登录信息和权限信息

package com.example.testsecurity.service;import com.example.testsecurity.mapper.UserMapper;
import com.example.testsecurity.pojo.MyUser;
import com.example.testsecurity.pojo.User;
import com.example.testsecurity.pojo.UserAuthority;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.Objects;@Service
@Slf4j
public class MyUserService implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate UserAuthorityService userAuthorityService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.findUserByName(username);UserAuthority userAuthority = userAuthorityService.findAuthorByUserId(user.getId());log.info(userAuthority.getAuthority());if (Objects.isNull(user)) {throw new UsernameNotFoundException("用户名不存在");}log.info("user" + username);MyUser myUser = new MyUser(user, userAuthority);return myUser;}
}
4.定义一个类实现UserDetails

实体类:

package com.example.testsecurity.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {private int id;private String name;private int roleId;@JsonIgnoreprivate String password; //忽略返回密码private int isExpired;private int isLocked;private int isEnable;private int credentialsExpired;}
package com.example.testsecurity.pojo;import com.example.testsecurity.service.UserAuthorityService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;//自定义用户信息
@Component
@AllArgsConstructor
@Data
@NoArgsConstructor
@Slf4j
public class MyUser implements UserDetails {private User user;private UserAuthority userAuthority;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {String[] authorities = userAuthority.getAuthority().split(",");    //由于数据库中authority字段里面是用","来分隔每个权限List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();for (String role : authorities) {simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role));}log.info(simpleGrantedAuthorities.get(0).getAuthority());return simpleGrantedAuthorities;}@Overridepublic String getPassword() {String password = user.getPassword();user.setPassword(null);// 擦除密码防止传到前端return password;}@Overridepublic String getUsername() {return user.getName();}@Overridepublic boolean isAccountNonExpired() {return user.getIsExpired() == 1;}@Overridepublic boolean isAccountNonLocked() {return user.getIsLocked() == 1;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return user.getIsEnable() == 1;}
}
package com.example.testsecurity.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserAuthority {private  int id;private String authority;}
5.编写测试controller
package com.example.testsecurity.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/lookZy")@PreAuthorize("hasAuthority('look:zy')")public String lookZy() {return "查看作业";}@GetMapping("/editZy")@PreAuthorize("hasAuthority('edit:zy')")public String editZy() {return "编辑作业";}@GetMapping("/delZy")@PreAuthorize("hasAnyAuthority('del:zy')")public String delZy() {return "删除作业";}
}
6.编写配置类并开启方法授权
package com.example.testsecurity.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;//从 Spring Security 5.7.0-M2开始 WebSecurityConfigurerAdapter 被标记为过期,鼓励用户转向基于组件的 security 配置
@Configuration
@Slf4j
//全局方法授权@EnableWebSecurity  // 启用SpringSecurity@EnableMethodSecurity
public class SecurityConfiguration {//认证成功处理器@Autowiredprivate AuthorSuccesssHandler authorSuccesssHandler;@Autowired//认证失败处理器private AuthorFailHandler authorFailHandler;//退出登录处理器@Autowiredprivate AppLoginOutHandler appLoginOutHandler;//访问拒绝处理器@Autowiredprivate AppAcessDeiedHandler appAcessDeiedHandler;@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.anyRequest().authenticated());http.formLogin().successHandler(authorSuccesssHandler)//认证成功.failureHandler(authorFailHandler)//认证失败.permitAll();http.logout().logoutSuccessHandler(appLoginOutHandler); //退出登录http.exceptionHandling().accessDeniedHandler(appAcessDeiedHandler);//访问资源失败return http.build();}//    @Bean
//    public WebSecurityCustomizer webSecurityCustomizer() {
//        return (web) -> web.ignoring().requestMatchers("/test/**");
//    }@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
7.登录测试查看用户信息并测试权限

在这里插入图片描述
张三用户信息
在这里插入图片描述

在这里插入图片描述

小李信息:
在这里插入图片描述

张三学生、和小李都可以访问的接口

在这里插入图片描述

在这里插入图片描述

小李可以访问的
在这里插入图片描述
张三访问不了资源
在这里插入图片描述
备注:两个mapper代码

package com.example.testsecurity.mapper;import com.example.testsecurity.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface UserMapper {@Select("select * from sys_user where name=#{username}")User findUserByName(String username);}package com.example.testsecurity.mapper;import com.example.testsecurity.pojo.UserAuthority;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserAuthorityMapper {UserAuthority findAuthorByUserId(Integer userId);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.example.testsecurity.mapper.UserAuthorityMapper"><select id="findAuthorByUserId" resultType="com.example.testsecurity.pojo.UserAuthority">SELECT * FROM `sys_authority`WHERE id=(SELECT `authority_id` from `sys_roles_authority`WHERE id=(SELECT `roles_id` FROM `sys_user_roles`WHERE `user_id`=#{userId}));</select></mapper>

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

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

相关文章

新媒体营销模拟实训室解决方案

一、引言 随着互联网的发展&#xff0c;新媒体已成为企业进行营销和品牌推广的重要渠道。然而&#xff0c;对于许多企业来说&#xff0c;如何在新媒体上进行有效的营销仍是一大挑战。为了解决这个问题&#xff0c;我们推出了一款新媒体营销模拟实训室解决方案&#xff0c;以帮…

【文末送书】Python OpenCV从入门到精通

文章目录 &#x1f354;简介opencv&#x1f339;内容简介&#x1f6f8;编辑推荐&#x1f384;导读&#x1f33a;彩蛋 &#x1f354;简介opencv OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;提供了丰富的图像处理和…

java学习part31String

142-常用类与基础API-String的理解与不可变性_哔哩哔哩_bilibili 1.String 2.字符串常量池 变更储存区的原因是加快被gc的频率 比地址&#xff0c;equals比内容 3.字符串连接 s3s4都是字符串常量&#xff0c;后面几个会利用StringBuilder的toString&#xff08;&#xff09;&a…

JAVA全栈开发 day16_MySql01

一、数据库 1.数据储存在哪里&#xff1f; 硬盘、网盘、U盘、光盘、内存&#xff08;临时存储&#xff09; 数据持久化 使用文件来进行存储&#xff0c;数据库也是一种文件&#xff0c;像excel &#xff0c;xml 这些都可以进行数据的存储&#xff0c;但大量数据操作&#x…

C#网络编程TCP程序设计(Socket类、TcpClient类和 TcpListener类)

目录 一、Socket类 1.Socket类的常用属性及说明 2.Socket类的常用方法及说明 二、TcpClient类 三、TcpListener类 四、示例 1.源码 2.生成效果 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在C#中&#xff0c;TCP程序设…

拼多多关键词搜索商品列表接口调用演示,关键词搜索接口,item_search - 按关键字搜索商品列表案例

拼多多关键词搜索商品API接口的作用主要是提供商品搜索功能&#xff0c;开发者可以根据用户输入的关键词进行商品搜索&#xff0c;返回符合条件的商品列表。这个接口可以帮助开发者在自己的应用程序中实现用户的注册、登录和信息维护等功能&#xff0c;并且可以查询订单的详细信…

react-flip-move结合array-move实现前端列表置顶效果

你有没有遇到这样的需求&#xff1f;点击左侧列表项&#xff0c;则像聊天会话窗口一样将被点击的列表项置顶。 如果只是单纯的置顶的话&#xff0c;直接使用array-move就可以实现了&#xff0c;但置顶效果多少有点突兀~ 先上代码&#xff0c;直接使用array-move的情况&#xf…

安卓手机网页如何阻止input框长按出现绿色水滴控件

在安卓手机的网页中&#xff0c;阻止输入框&#xff08;input框&#xff09;长按时出现的绿色水滴控件&#xff08;这通常是文本选择控件&#xff09;&#xff0c;可以通过一些CSS和JavaScript技巧来实现。这些控件通常用于文本选择和编辑&#xff0c;但在某些情况下&#xff0…

Ansible及其优势是什么?

Ansible是一款极其简单的开源的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具(puppet, cfengine, chef, func, fabric)的优点。实现了批量系统配置&#xff0c;批量程序部署&#xff0c;批量运行命令等功能。同时Ansible是基于模块工作&#xff0c;…

数据可视化私有化部署:为何成本居高不下?

尽管在可视化设计这行干了好多年&#xff0c;也接手过不少项目&#xff0c;但昂贵的私有化部署费用总能让我发出由衷的感叹&#xff1a;“这几十万一年也太贵了&#xff01;”。可以预见&#xff0c;数据可视化软件私有化部署所带来的高昂成本&#xff0c;将是许多企业面临的问…

Jmeter进行压力测试不为人知的秘密

jmeter是apache公司基于java开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简单。因为jmeter是java开发的&#xff0c;所以运行的时候必须先要安装jdk才可以。jmeter是免…

每日一练【快乐数】

一、题目描述 202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这…

Hive_Spark_left()函数

在SQL中&#xff0c;LEFT()函数是一个字符串函数&#xff0c;用于从一个字符串的左侧开始提取指定数量的字符。这个函数通常接受两个参数&#xff1a; 第一个参数是要从中提取字符的字符串。 第二个参数指定要提取的字符数。 语法如下&#xff1a; LEFT(string_expression,…

Elasticsearch高级

文章目录 一.数据聚合二.RestAPI实现聚合三.ES自动补全(联想)四.数据同步五.elasticsearch集群 一.数据聚合 在ES中的数据聚合&#xff08;aggregations&#xff09;可以近似看做成mysql中的groupby分组,聚合可以实现对文档数据的统计、分析、运算,常见的聚合的分类有以下几种…

源代码编译cuda opencv

先下载opencv 从这里https://opencv.org/releases/ 下载最新版本的opencv-4.8.0-windows.exe 从这里https://github.com/opencv/opencv_contrib/tags 下载opencv的扩展版本&#xff0c;这个是cuda对cuda的支持 下载cmake 从这里https://cmake.org/files/v3.28/下载最新版本最新…

基于APM(PIX)飞控和mission planner制作遥控无人车-从零搭建自主pix无人车普通舵机转向无人车-1(以乐迪crossflight飞控为例)

1.前期准备 准备通过舵机转向的无人车地盘、遥控器、地面站电脑、飞控等。安装驱动程序、端口程序、netframwork等&#xff0c;不再赘述。 2.安装固件 安装ardurover固件&#xff0c;如果在线失败&#xff0c;选择官方最新的固件下载到本地&#xff0c;选择本地安装。 3.调试…

智能仓库PTL管理系统

清晰电子墨水屏显示&#xff0c;无纸化作业&#xff0c;超低功耗 无线通信&#xff0c;穿透力强&#xff0c;极简部署 支持声光提醒&#xff0c;极大提高作业效率 适用场景&#xff1a;工厂&#xff0c;仓库&#xff0c;物流&#xff0c;货品分类等等

阿里千问Qwen-72 b在中文测试中击败了GPT-3.5

2023.11.30 我们在 ModelScope 和 Hugging Face 上发布了Qwen-72B和Qwen-72B-Chat&#xff0c;它们在 3T 令牌上进行训练并支持 32k 上下文&#xff0c;以及Qwen-1.8B和Qwen-1.8B-Chat 。 我们还增强了 Qwen-72B-Chat 和 Qwen-1.8B-Chat 的系统提示功能&#xff0c;请参阅示例…

认识Docker

Docker 是世界领先的软件容器平台&#xff0c;所以想要搞懂 Docker 的概念我们必须先从容器开始说起。 1.1 什么是容器? 先来看看容器较为官方 一句话概括容器&#xff1a;容器就是将软件打包成标准化单元&#xff0c;以用于开发、交付和部署。 容器镜像是轻量的、可执行的…