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

news2024/11/25 21:13:30
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 {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserAuthorityService userAuthorityService;

    @Override
    public 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;


    @JsonIgnore
    private 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;

    @Override
    public 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;

    }

    @Override
    public String getPassword() {
    
         String password = user.getPassword();
        user.setPassword(null);// 擦除密码防止传到前端
        return password;
    }

    @Override
    public String getUsername() {
        return user.getName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return user.getIsExpired() == 1;
    }

    @Override
    public boolean isAccountNonLocked() {
        return user.getIsLocked() == 1;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public 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 {

    //认证成功处理器
    @Autowired
    private AuthorSuccesssHandler authorSuccesssHandler;
    @Autowired
    //认证失败处理器
    private AuthorFailHandler authorFailHandler;

    //退出登录处理器

    @Autowired
    private AppLoginOutHandler appLoginOutHandler;

    //访问拒绝处理器
    @Autowired
    private AppAcessDeiedHandler appAcessDeiedHandler;


    @Bean
    public 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/**");
//    }

    @Bean
    public 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 mapper
        PUBLIC "-//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.coloradmin.cn/o/1292220.html

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

相关文章

linux高级篇基础理论七(Tomcat)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

主食罐头哪个牌子好?猫主食罐头品牌盘点

养猫的这几年德罐也买了不少了&#xff0c;很早以前德罐给我的感觉就是&#xff0c;物美价廉&#xff0c;而且质量保障也不错&#xff0c;很美丽。但最近的德罐恕在下高攀不起了。 猫罐头侠登场&#xff01;养猫这么久了我就把我吃的不错的猫罐头分享一下&#xff01;别纠结了…

Dockerfile 指令的最佳实践

这些建议旨在帮助您创建一个高效且可维护的Dockerfile。 一、FROM 尽可能使用当前的官方镜像作为镜像的基础。Docker推荐Alpine镜像&#xff0c;因为它受到严格控制&#xff0c;体积小&#xff08;目前不到6 MB&#xff09;&#xff0c;同时仍然是一个完整的Linux发行版。 FR…

【FPGA】Quartus18.1打包封装网表文件(.qxp)详细教程

当我们在做项目的过程中&#xff0c;编写的底层Verilog代码不想交给甲方时怎么办呢&#xff1f;此时可以将源代码打包封装成网表文件&#xff08;.qxp&#xff09;进行加密&#xff0c;并且在工程中进行调用。 Quartus II的.qxp文件为QuartusII Exported Partition&#xff0c;…

马来西亚虾皮选品工具:如何优化您的电商业务

随着电子商务的快速发展&#xff0c;越来越多的商家开始将目光投向在线市场。在马来西亚&#xff0c;虾皮&#xff08;Shopee&#xff09;平台成为了一个备受瞩目的电商平台&#xff0c;吸引了大量的商家和消费者。然而&#xff0c;要在这个竞争激烈的市场中脱颖而出并取得成功…

基于JavaSE+JDBC使用控制台操作的简易购物系统【源码+数据库】

1、项目简介 本项目是一套基于JavaSEJDBC使用控制台操作的简易购物系统&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&…

计算n的阶乘-递归与迭代之间的相爱相杀

n的阶乘是指从1连乘到n的结果&#xff0c;通常用符号n!表示。例如&#xff0c;3的阶乘表示为3!&#xff0c;计算过程如下&#xff1a; 3! 3 2 1 6 一般地&#xff0c;n的阶乘可以用递归或迭代的方式计算&#xff0c;公式为&#xff1a; n! n (n-1) (n-2) ... 2 1 …

UEM 在企业 IT 管理数字化转型有什么帮助

近年大多数公司都在努力实现数字化转型&#xff0c;业务应用程序正在迁移到云端&#xff0c;日常 IT 运营正变得更加面向移动化&#xff0c;高管们使用各种设备。员工不仅使用公司提供的台式机&#xff0c;还经常使用公司拥有的、个人启用的&#xff08;COPE&#xff09;笔记本…

浅析AI智能视频监控技术在城市交通中的作用及意义

城市交通作为整个城市的整体脉络&#xff0c;每天都发挥着重要作用&#xff0c;为了最大程度地避免城市交通堵塞、提高城市交通效率&#xff0c;智能视频监控系统发挥了重要作用。具体表现在以下几个方面&#xff1a; 1、交通违规监管&#xff1a;TSINGSEE青犀智能视频监控系统…

LeetCode刷题--- 计算布尔二叉树的值

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏&#xff1a;http://t.csdnimg.cn/ZxuNL http://t.csdnimg.cn/c9twt 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#xff0c;所以下面题目主要也是这些算法做的 我讲述…

反钓鱼防盗号,共筑校园安全防线!Coremail出席CERNET学术年会

11月27日-30日&#xff0c;中国教育和科研计算机网CERNET第二十八/二十九届学术年会在福州隆重举办&#xff0c;Coremail受邀出席&#xff0c;就高校数字化及网络安全等相关话题与高校老师、行业专家进行广泛交流。 △11月27-30日&#xff0c;Coremail在会场设展&#xff0c;为…

Vue实现注册页面的用户交互

&#x1f4d1;前言 本文主要是【Vue】——Vue实现注册页面的用户交互的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每…

CRM客户管理系统,不止管理客户。

CRM系统现在已经成为企业与客户建立良好关系、提高销售业绩的优先选择。关于CRM的功能&#xff0c;不同的企业包括CRM软件厂商都对CRM系统有不同的定义。基于此&#xff0c;我们来聊聊CRM客户管理系统除了管客户还有什么功能&#xff1f; 1、客户管理 有些企业管理客户的方式…

【互斥锁不当使用导致的条件竞争】2021_DiceCTF_hashbrown

前言 这个题目还挺有意思的&#xff0c;他并不像之前做的题目直接给你一个贴脸的 UAF 等&#xff0c;而是把 UAF 放在了条件竞争的环境下&#xff0c;其实条件竞争这个漏洞在内核中经常出现。 这里题目没有去符号&#xff0c;所以逆向的难度不是很大&#xff0c;但作者似乎在…

【Axure教程】树筛选中继器表格

树和表格是信息系统中两个重要的元件&#xff0c;树结构是一种层次化的数据结构&#xff0c;它以树的形式展示数据的层次关系&#xff1b;表格是一种二维结构&#xff0c;由行和列组成。每一行表示一个记录&#xff0c;每一列表示一个属性。在实际应用中&#xff0c;这两种结构…

陈睿接手一年后,B站全力一搏的游戏业务怎样了

11月末&#xff0c;哔哩哔哩公布了截至2023年9月30日的第三季度财报。 就在去年的这个时候&#xff0c;陈睿宣布亲自接手了B站的游戏业务。因为做游戏比给游戏打广告利润高&#xff0c;因为自研游戏利润更高&#xff0c;更因为年年亏损的B站需要这么高利润的业务来拯救。 但一…

Python文件操作(txt + xls + json)

文章目录 简介1、使用with_open读取和保存&#xff1a;.txt .bin&#xff08;二进制文本&#xff09;1.1、with open语句详解1.1、项目实战 2、使用pandas读取和保存&#xff1a;.xls .xlsx2.1、pandas简介2.2、环境配置2.3、项目实战 3、 使用json.dump读取和保存&#xff1…

MS8091/2运算放大器可Pin to Pin兼容AD8091/2

MS809x 系列是一种易用的、低成本的轨到轨输出电压反馈放大器&#xff0c;它具有典型的电流反馈放大器带宽和转换率的优势&#xff0c;同时也有较大的共模电压输入范围和输出摆幅&#xff0c;这使它很容易在单电源 2.5V 的低压情况下工作。可Pin to Pin兼容AD8091/AD8092。 虽然…

速达软件任意文件上传漏洞复现

简介 速达软件专注中小企业管理软件,产品涵盖进销存软件,财务软件,ERP软件,CRM系统,项目管理软件,OA系统,仓库管理软件等,是中小企业管理市场的佼佼者,提供产品、技术、服务等信息,百万企业共同选择。速达软件全系产品存在任意文件上传漏洞,未经身份认证得攻击者可以通过此漏…

Android渲染-AHardwareBuffer

本文主要从应用的角度介绍android的native层AHardwareBuffer创建纹理以及保存渲染数据。 HardwareBuffer 要介绍native层的AHardwareBuffer&#xff0c;就需要先从Java层的HardwareBuffer说起。Android官方对于HardwareBuffer介绍如下&#xff1a; HardwareBuffer wraps a na…