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 {

    @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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Scopus检索】第六届生物技术与生物医学国际学术会议(ICBB 2024)

第六届生物技术与生物医学国际学术会议 2024 6th International Conference on Biotechnology and Biomedicine (ICBB 2024) 第六届生物技术与生物医学国际学术会议&#xff08;ICBB 2024&#xff09;将于2024年03月29日-3月31日在中国-武汉市召开。ICBB 2024将围绕“生物技术…

安装mysql数据库

1.1下载APT存储库&#xff08;下载链接&#xff09; 1.2安装APT存储库&#xff08;注意好正确的路径&#xff09; 将下载的文件传输到linux服务器对应目录下后执行以下命令&#xff1a; sudo dpkg -i mysql-apt-config_0.8.10-1_all.deb 选择mysql5.7 然后点击ok 然后执行 s…

vagrant up卡死问题

环境 OS&#xff1a;Windows 10Vagrant&#xff1a;Vagrant 2.2.14VirtualBox&#xff1a;6.1.18 r142142box&#xff1a;CentOS-7-x86_64-Vagrant-2004_01.VirtualBox.box 详细信息 解决办法 修改文件Vagrantfile&#xff0c;增加如下配置&#xff0c;测试可以正常启动 conf…

redis配置介绍

redis配置详解 一、redis.conf二、持久化1、RDB① 触发机制② 优缺点③ 恢复rdb 2、AOF① 优缺点② 恢复aof 三、发布订阅 一、redis.conf # -----NETWORK----- # 设置绑定ip bind 127.0.0.1 -::1 # 设置redis保护&#xff0c;只能通过绑定在本地回环地址上的网络接口进行访问…

股票代码合法验证:python字符串str应用

从键盘输入六位股票代码字符串&#xff0c;判定合法并输出板块分类&#xff0c;否则输出“NO”。 (笔记模板由python脚本于2023年12月04日 19:19:07创建&#xff0c;本篇笔记适合熟悉python字符串和字典的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https:…

C语言实现Berzier曲线几何作图算法

前言&#xff1a; 隐式曲线表达上的限制 计算上的多值性&#xff08;例如可能一个 x 对应多个 y&#xff09;存在导数 未定义的点坐标系进行变换后&#xff0c;曲线表达形式将可能会发生改变 一般的多项式幂基函数缺乏直观的几何意义 我们考虑由3个二元点对构造的二维平面曲…

使用正则表达式时-可能会导致性能下降的情况

目录 前言 正则表达式引擎 NFA自动机的回溯 解决方案 前言 正则表达式是一个用正则符号写出的公式&#xff0c;程序对这个公式进行语法分析&#xff0c;建立一个语法分析树&#xff0c;再根据这个分析树结合正则表达式的引擎生成执行程序(这个执行程序我们把它称作状态机&a…

6、原型模式(Prototype Pattern,不常用)

原型模式指通过调用原型实例的Clone方法或其他手段来创建对象。 原型模式属于创建型设计模式&#xff0c;它以当前对象为原型&#xff08;蓝本&#xff09;来创建另一个新的对象&#xff0c;而无须知道创建的细节。原型模式在Java中通常使用Clone技术实现&#xff0c;在JavaSc…

参加百度Apollo技术沙龙—感受自动驾驶的魅力

2023年12月2日下午2点&#xff0c;我有幸参加了百度Apollo技术沙龙&#xff0c;这是一个围绕Apollo新版本Beta的全面升级展开的深度交流活动。作为一名工程师&#xff0c;我深感荣幸能够与众多同行和专家一同探讨自动驾驶技术的快速发展 在这次沙龙中&#xff0c;我了解到Apo…

可编程电子负载原理是怎样的

可编程电子负载是一种模拟真实负载的电子设备&#xff0c;它可以模拟各种不同类型和规格的负载&#xff0c;如电阻、电容、电感等。通过调整电子负载的参数&#xff0c;可以实现对电源输出电压、电流、功率等性能指标的精确控制。可编程电子负载广泛应用于电源测试、电池充放电…

基于vue+node.js智慧校园学生办证系统

基于vuenode.js智慧校园学生办证系统 摘要&#xff1a;随着计算机技术和网络技术的飞快发展&#xff0c;它加速了国内信息化建设的进程&#xff0c;信息技术对管理改革产生了深远的影响。为了适应新时代的发展趋势&#xff0c;各行各业都高度重视信息化建设。在教育领域&#…

成为Java开发高手:掌握Spring框架的关键技能-DI

DI相关内容 1.1 setter注入1.1.2 注入引用数据类型1.1.3 注入简单数据类型步骤1:声明属性并提供setter方法步骤2:配置文件中进行注入配置步骤3:运行程序 1.2 构造器注入1.2.2 构造器注入引用数据类型步骤1:删除setter方法并提供构造方法步骤2:配置文件中进行配置构造方式注入步…

4.9 构建onnx结构模型-Equal

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Equal 结点进行分析 方式 方法一…

北京华联BHGMall“宠粉模式”不断迭代,强体验注互动成行业UP主

在今年双11热度遇冷后&#xff0c;双十二被官宣取消&#xff0c;而这背后本质已经间接印证&#xff1a;传统“电商大促”的模式&#xff0c;已经难以为继。反观线下消费市场&#xff0c;则是以持续恢复和增长成为经济恢复的亮点&#xff0c;从线下客流量的快速回升&#xff0c;…

软考2016年上半年第六题(适配器模式)与手术训练系统项目适配器模式的应用

软考2016年上半年第六题 public class Address {public void street(){System.out.println("a");};public void zip(){};public void city(){}; }package org.example.适配器模式;/*** 适配器模式&#xff08;Adapter Pattern&#xff09;是作为两个不兼容的接口之间…

整数和浮点数在内存中的存储​(大小端详解)

目录 一、整数在内存中的存储 二、大小端字节序和字节序判断 2.1为什么有大小端?​ 2.2请简述大端字节序和小端字节序的概念&#xff0c;设计一个小程序来判断当前机器的字节序。&#xff08;10分&#xff09;-百度笔试题 方法一&#xff08;char*强制类型转换&#xff09…

疑难杂症 之 关闭模态窗口之后刷新父窗口

疑难杂症 之 关闭模态窗口之后刷新父窗口 1. 模态窗口 与 非模态窗口2. 弹出模态窗口2.1 实现效果2.2 实现代码2.2.1 刷新父窗口2.2.2 完整代码 2.3 参考 3. 其他刷新父窗口&#xff08;模态窗口页面与父窗口不在同一页面&#xff09;3.1 实现代码3.1.1 核心代码3.1.2 多层模态…

什么是Amazon Lambda(无服务器计算服务)

Lambda 在高可用性计算基础设施上运行代码&#xff0c;用于执行计算资源的所有管理工作。这包括服务器和操作系统维护、容量调配和弹性伸缩、代码和安全补丁部署以及代码监控和日志记录。您只需要提供代码。 最近亚马逊云服务提供了超多免费的云服务&#xff0c;快来领取免费套…

java版微信小程序商城免费搭建 java版直播商城平台规划及常见的营销模式有哪些?电商源码/小程序/三级分销

涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis …