Springboot +spring security,基于默认数据库模型实现授权

news2025/4/7 15:42:52

一.简介

上一篇文章中讲解了如何基于内存模型来实现授权,在这种模型里,用户的信息是保存在内存中的。但是,保存在内存中的信息,是无法持久化的,也就是程序一旦关闭,或者断电等情况发生,内存中的信息就丢失了,所以这种方式并不适用于生产环境。

那么肯定就要把用户信息持久化, 持久化到数据库,这边文章中采用的是MySQL数据库。

二.JdbcUserDetailsManager类

在数据库中创建并保存用户及角色信息,Spring Security给我们提供了另一个UserDetailsService的实现子类,就是JdbcUserDetailsManager。其中JdbcUserDetailsManager类的关系结构如下图所示:
在这里插入图片描述
从上图中,可以看到JdbcUserDetailsManager的直接父类是JDBCDaoSuport,利用JdbcUserDetailsManager可以帮助我们以JDBC的方式对接数据库进行增删改查等操作。它内部设定了一个默认的数据库模型,只要遵从这个模型,我们就可以很方便的实现在数据库中创建用户名和密码、角色等信息,但是灵活性不足。

三. 创建SpringSecurity项目

参考之前的文章,这边不做叙述。

四. 基于默认数据库模型实现授权

3.1创建测试接口

在开始授权代码之前,先创建3个用于测试的Web接口,分别供3个不同的用户角色来进行操作。

3.1.1创建/admin/hello接口:

AdminController 类代码如下:

@RestController
@RequestMapping("/admin")
public class AdminController {
 
    @GetMapping("/hello")
    public String hello() {
        return "hello, admin";
    }
}

3.1.2创建/user/hello接口:

UserController 类代码如下:

@RestController
@RequestMapping("/user")
public class UserController {
 
    @GetMapping("hello")
    public String hello() {
        return "hello, user";
    }
}

3.1.3创建/visitor/hello接口:

VisitorController 类代码如下:

@RestController
@RequestMapping("/visitor")
public class VisitorController {
 
    @GetMapping("/hello")
    public String hello() {
        return "hello, visitor";
    }
}

对于以上三个接口,做如下解释:

  1. /visitor/hello 任何人都可以访问;
  2. /admin/hello 具有 admin 角色的人才能访问;
  3. /user/hello 具有 user 角色的人才能访问;
  4. 所有 user 角色能够访问的接口资源,admin 角色也都能够访问。

4.2准备数据库

既然要操作数据库,那肯定得先建库建表,JdbcUserDetailsManager本身就给我们提供了对应的数据库脚本模型,这个数据库脚本模型保存在如下位置:

org/springframework/security/core/userdetails/jdbc/users.ddl

截图如下:
在这里插入图片描述
直接去这个对应的位置下,找到这个数据库脚本文件打开即可。

当打开这个users.ddl文件,可以看到如下内容,会发现其中有2个建表语句,分别是创建了users表和authorities表,并且在authorities表中创建了唯一索引。代码如下:

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);
 
create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
 
create unique index ix_auth_username on authorities (username,authority);

放到navicat中,创建即可。

注意:

上面的建表脚本中,有一种数据类型 varchar_ignorecase,这个是针对 HSQLDB 数据库创建的,但是我们使用的 MySQL 数据库并不支持这种数据类型,所以这里需要手动将这个数据类型改为 varchar。

4.3配置资源访问权限

先定义一个SecurityConfig配置类,在其中配置对资源的访问控制,创建一个UserDetailsService实例,并在其中配置,生成存储用户和角色信息,代码如下:

@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("/user/**")
                .hasRole("USER")
                .antMatchers("/app/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll();
    }
 
    /***************************************在默认的数据库中创建用户和角色****************************************************/
 
    @Autowired
    private DataSource dataSource;
 
    @Bean
    public UserDetailsService createUserDetailService() {
        JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
        manager.setDataSource(dataSource);
 
        if (!manager.userExists("user")) {
            manager.createUser(User.withUsername("user").password("123").roles("USER").build());
        }
 
        if (!manager.userExists("admin")) {
            manager.createUser(User.withUsername("admin").password("123").roles("USER", "ADMIN").build());
        }
        
        return manager;
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
}

4.4代码释义

要针对createUserDetailService()方法进行解释。

  1. 在这个方法中,我们首先构建一个 JdbcUserDetailsManager 实例对象,并给 JdbcUserDetailsManager 实例添加一个 DataSource 对象。
  2. 接下来调用 userExists()方法 判断用户是否存在,如果不存在,就创建一个新的用户出来(因为每次项目启动时这段代码都会执行,所以加一个判断,避免重复创建用户)。
  3. 用户的创建方法和我们之前 InMemoryUserDetailsManager 中的创建用户的方法基本一致。

以上就是我们基于默认的数据库模型实现的对用户及角色的操作,之所以可以实现,就是因为在UserDetailsManager这个父接口中,定义了如下方法,这些方法在子类中都有具体的实现。截图如下:
在这里插入图片描述
可以看到UserDetailsManager类中,提供了创建、修改、删除、判断用户是否存在的方法,和修改用户密码的方法。

在JdbcUserDetailsManager这个实现子类中,已经定义好了users与authorities表对应的CRUD语句,所以我们直接调用相关方法即可实现对用户及角色的管理。另外我们在特殊情况下,也可以自定义这些SQL语句,如有需要,调用对应的setXxxSQL()方法即可。
在这里插入图片描述

五.验证

项目启动起来,然后以不同的身份登录进来,分别访问不同的接口,当某个用户在不具备相应角色时,会出现403提示信息。只有具有相应的角色权限时,才可以访问对应的接口。截图如下:
在这里插入图片描述

当我们使用Spring Security默认的数据库模型来操作实现用户授权时,存在灵活性不足的问题,因为我们必须按照源码规定的方式去建库建表。而我们真正开发时,用户角色等表肯定是根据自己的项目需求来单独设计的,所以真正开发时,我们有必要进行用户及角色表的自定义设计。

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

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

相关文章

0基础学习VR全景平台篇第36篇:场景功能-导览

大家好,欢迎观看蛙色VR官方系列——后台使用课程! 本期为大家带来蛙色VR平台,场景管理—导览功能操作。 功能位置示意 一、本功能将用在哪里? 导览,指给VR漫游作品预先设置好路线,并且可以自定义路线的旋…

DMBOK知识梳理for CDGA/CDGP——第三章数据治理

关 注gzh“大数据食铁兽” 回复“知识点”获取《DMBOK知识梳理for CDGA/CDGP》常考知识点(第三章数据治理) 第三章 数据治理 第三章在是CDGA|CDGP考试的重点考核章节之一,知识点比较密集,本章重点为语境关系图及数据治理概念…

初心不改凌云志 热血浇灌信仰花 《凭栏一片风云起》湖北卫视热力开播

浮光灼夏 御风而行, 由著名导演金琛执导, 胡一天、章若楠、王劲松 张晞临、张赫、林子璐领衔主演, 高伟光特邀出演的 年代战争剧《凭栏一片风云起》, 将于今晚19:30起, 登陆【湖北卫视】长江剧场。 电视剧《凭栏…

音乐人解密:究竟是如何一步一步成为音乐人的?

音乐人解密:究竟是如何一步一步成为音乐人的? 音乐是人类伟大的产物,近些年来越来越多的人都开始尝试学习音乐,成为一名音乐人。而艺术高考等途径也为许多想要学习音乐、成为职业歌手或者编曲师的人群提供了途径。然而想要成为一名…

初识EasyUI

2.1何为EasyUI. EasyUI的全称是“JQuery EasyUI”,是一种基于jQuery、Angular、Vue和React的用户界面的插件的集合,EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂的javascript,也不需要对css样…

【Protobuf速成指南】Win/Centos7下Protobuf安装教程

文章目录 安装教程一、Windows1.1 下载编译器1.2 配置PATH1.3 其他依赖项 二、Centos72.1 安装必要的工具2.2 下载安装包2.3 安装 安装教程 以版本为V21.11为例说明 一、Windows 1.1 下载编译器 下载地址:链接,一直往下翻找到 V21.11版本 win用户根据…

火爆全网,最全性能测试从0到1进阶总结,高阶内卷学习路线...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 例如:…

ArduPilot飞控开源代码之滤波设置

ArduPilot飞控开源代码之滤波设置 1. 源由2. 原理3. 调优3.1 ACC低通滤波 INS_ACCEL_FILTER3.2 GRYO低通滤波 INS_GYRO_FILTER3.3 陷波滤波 INS_HNTCH_ENABLE & INS_HNTC2_ENABLE 4. 总结5. 参考资料 1. 源由 对于飞控传感器来来说,振动噪声也是数据。 单纯从数…

yolov3

文章目录 前言一、主干网络darknet53二、从特征获取预测结果 前言 本文主要讲解yolov3的基本知识,如有错误请指出。 本文主要来自 博客1 博客2 一、主干网络darknet53 53是因为有53层。 1、darknet53没有使用pooling 来进行下采样,而是用一个33&…

电脑数据隐藏原因有哪些?电脑里隐藏的数据怎么恢复

电脑里隐藏的数据怎么恢复?电脑中的数据很容易被隐藏,这时候很多人可能会感到焦急和无助。不过不用担心,本文将为大家介绍三种方法,让你轻松找回被隐藏的数据! ※电脑数据隐藏原因有哪些 电脑数据可能会隐藏&#xf…

100天精通Golang:全面掌握Go语言的旅程

🌷 博主 libin9iOak带您 Go to Golang Language.✨ 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《I…

QLoRA:量化 LLM 的高效微调

此 repo 支持论文“QLoRA:量化 LLM 的高效微调”,旨在使对 LLM 研究的访问民主化。 QLoRA 使用bitsandbytes进行量化,并与 Hugging Face 的PEFT和transformers库集成。QLoRA 由华盛顿大学 UW NLP 小组的成员开发。 概述 我们介绍了 QLoRA&…

volatile - (C语言)

volatile关键字和const一样都是一种类型修饰符,用它修饰过的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者是其它线程等。 该关键字是不希望被编译器优化,从而达到稳定访问内存的目的。 示例代码: #include&…

FlinkUI和Flink常见问题解决

Flink 系统架构/Flink 作业提交运行的原理 我们编写的代码,对应着在Flink集群上执行的一个作业;所以我们在本地执行代码, 其实是idea开发环境中根据引入的依赖,先模拟启动一个Flink集群,然后把我们代码中定义好的操作,作为"作业",(job要打包好)然后将作业提…

双出口网络链路和设备双冗余案例

1、AR3模拟联通和电信运营商 2、2台防火墙vrrphrp双冗余,下联局域网vrrp 10.3.0.3地址,上联两条外线每条外线都分别vrrp虚拟一个地址1.1.1.1.和2.2.2.2.1。 3、防火墙外线地址和运营商给的外线地址不在同一个网段,每条都用vrrp冗余链路&#…

安装第三方库时的问题—复现带setup.py的项目

目录 题目分析: 正片开始: 题目分析: 事情的经过大致是这样: 今天在github上拿到一个处理时间序列的迁移学习项目的复现代码,项目文件如下所示: 或者我们来关注一下tl4sm这个文件夹里的东西&#xff1…

Tomcat的部署和优化(生命中的全部偶然,其实都是命中注定)

文章目录 一、Tomcat简介二、Tomcat 的构成三、Tomcat 功能组件结构四、Tomcat 请求过程五、Tomcat 服务部署六、Tomcat 虚拟主机配置七、Tomcat优化1.Tomcat 配置文件参数优化2.JVM优化 一、Tomcat简介 Tomcat 是 Java 语言开发的,Tomcat 服务器是一个免费的开放源…

【shiro】问题记录--为什么refreshToken方法走不下去

一、前言 最近做Jwt token续签的时候,在很多博客和下载的代码中,都是在JWTFilter中进行token的刷新,于是就按照了网上的代码进行尝试,代码如下: 1. 代码 在JWTFilter中的isAccessAllowed方法 目的:就是想…

STM32单片机RS485远程PID直流电机调速系统光电传感器

实践制作DIY- GC0137-RS485远程PID直流电机调速系统 基于STM32单片机设计-RS485远程PID直流电机调速系统 二、功能介绍: 主机:STM32F103C系列最小系统LCD1602直流电机光电测速MX15系列驱动模块4*4矩阵键盘RS485收发电路 从机:STM32F103C系…

Kubernetes配置管理

1. ConfigMap简介 Kubernetes ConfigMap是一种用于存储应用程序配置信息的对象。在企业中,我们通常会有许多不同的应用程序,每个应用程序都需要一些配置信息,例如数据库连接字符串、API密钥等等。这些配置信息可能会因为环境的不同而有所不同…