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.hqwc.cn/news/256428.html

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

相关文章

硬件基础:运放

理想运算放大器 理想运算放大器放大倍数无穷大&#xff1b;输入端阻抗无穷大&#xff0c;所以输入端电流为0&#xff1b;输出电压和负载无关&#xff0c;不管负载怎么变化&#xff0c;输出电压都是固定的。 还有个就是输出阻抗为0&#xff1b; 输出阻抗越小&#xff0c;输出时就…

12.Java程序设计-基于Springboot框架的Android学习生活交流APP设计与实现

摘要 移动应用在日常生活中扮演着越来越重要的角色&#xff0c;为用户提供了方便的学习和生活交流渠道。本研究旨在设计并实现一款基于Spring Boot框架的Android学习生活交流App&#xff0c;以促进用户之间的信息分享、学术交流和社交互动。 在需求分析阶段&#xff0c;我们明…

Python机器学习、深度学习入门丨气象常用科学计算库、气象海洋常用可视化库、爬虫和气象海洋数据、气象海洋常用插值方法、EOF统计分析、WRF模式后处理等

目录 专题一 Python软件的安装及入门 专题二 气象常用科学计算库 专题三 气象海洋常用可视化库 专题四 爬虫和气象海洋数据 专题五 气象海洋常用插值方法 专题六 机器学习基础理论和实操 专题七 机器学习的应用实例 专题八 深度学习基础理论和实操 专题九 深度学习的应…

企业级 接口自动化测试框架:Pytest+Allure+Excel

1. Allure 简介 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具&#xff0c;它不仅以 Web 的方式展示了简介的测试结果&#xff0c;而且允许参与开发过程的每个人可以从日常执行的测试中&#xff0c;最大限度地提取有用信息。 Allure 是由 Java 语言开发…

低代码是伪需求吗?它会让程序员失业吗?它是行业毒瘤吗?我对低代码开发的看法

一、什么是低代码 低代码是一种通过可视化进行应用程序开发的方法&#xff0c;它可以使具有不同经验水平的开发人员通过图形化的用户界面&#xff0c;使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程序。 低代码开发平台使非技术开发人员可以不必编写代码&#xff0c;而…

JavaSE基础50题:11. 输出一个整数的每一位

概述 输出一个整数的每一位。 如&#xff1a;1234的每一位是4&#xff0c;3&#xff0c;2&#xff0c;1 。 个位&#xff1a;1234 % 10 4 十位&#xff1a;1234 / 10 123 123 % 10 3 百位&#xff1a;123 / 10 12 12 % 10 2 千位&#xff1a; 12 / 10 1 代码 ublic sta…

LLM(五)| Gemini:谷歌发布碾压GPT-4最强原生多模态,语言理解能力首次超过人类

2023年12月6日&#xff0c;Google重磅发布了原生多模态大模型Gemini&#xff0c;碾压GPT-4&#xff0c;语言理解能力首次超过人类。 一、Gemini介绍 以下内容来自谷歌DeepMind首席执行官兼联合创始人Demis Hassabis代表Gemini团队&#xff1a; 人工智能一直是我一生工作的重点…

畅游分布式劳动力世界...

不断变化的软件开发环境继续为开发人员和雇用开发人员的企业带来新的机遇和挑战。无论是量子计算方面的突破、推动游戏行业增长的扩展现实开发&#xff0c;还是监管环境日益复杂的情况&#xff0c;DevOps 社区在来年都有很多事情要做。对于旨在确保未来盈利的企业来说&#xff…

边缘计算与人工智能的融合

随着物联网技术的迅猛发展&#xff0c;大量设备和传感器开始连接至互联网&#xff0c;产生了海量的数据。传统的云计算模式往往无法满足对数据实时性和隐私保护的需求&#xff0c;而边缘计算技术的兴起为解决这一难题提供了新的思路。边缘计算将数据处理和分析的功能下沉至数据…

从Centos-7升级到Centos-Stream-8

如果在正式环境升级&#xff0c;请做好数据备份以及重要配置备份&#xff01;因为升级会造一部分应用被卸载。 注意&#xff1a;升级前请备份好数据&#xff0c;升级可能会导致ssh的root用户无法登陆、网卡名称发生改变、引导丢失无法开机等问题。 1.安装epel源 yum -y install…

架构师-2.数据权限

数据权限,实现指定用户可以操作指定范围的数据。例如说,针对员工信息的数据权限: 上述的这个示例,使用硬编码是可以实现的,并且也非常简单。但是,在业务快速迭代的过程中,类似这种数据需求会越来越多,如果全部采用硬编码的方式,无疑会给我们带来非常大的开发与维护成…

【Java数据结构 -- List和ArrayList与顺序表】

List和ArrayList与顺序表 一. List1.1 List介绍2.1 常见接口介绍3.1 List的使用 二. ArrayList与顺序表1.线性表2.顺序表2.1 接口的实现 3.ArrayList简介4. ArrayList使用4.1 ArrayList的构造 4.2 ArrayList常见操作4.3 ArrayList的遍历4.4 ArrayList的扩容机制5. ArrayList的具…