后端进阶之路——万字总结Spring Security与数据库集成实践(五)
前言

「作者主页」:雪碧有白泡泡
「个人网站」:雪碧的个人网站
「推荐专栏」:
★java一站式服务 ★
★前端炫酷代码分享
★ ★ uniapp-从构建到提升★
★ 从0到英雄,vue成神之路★
★ 解决算法,一个专栏就够了★
★ 架构咱们从0说★
★ 数据流通的精妙之道★★后端进阶之路★

文章目录
- 前言
- 1. 引言
- 使用数据库集成Spring Security的目的和好处
- 2. 数据库设计与配置
- 2.1 用户表的结构和字段
- 2.2 角色表的结构和字段
- 2.3 配置Spring Security与数据库的连接
- 3. 用户认证
- 3.1 实现基于数据库的用户认证功能
- 3.2 使用Spring Security的Encoder进行密码加密和验证
- 4.3 自定义用户认证的逻辑和处理方式
- 4. 用户授权
- 4.1 基于数据库的用户授权功能
- 4.2 在数据库中定义角色和权限
- 4.3 配置权限验证规则和授权方式
- 4.4 自定义用户授权的逻辑和处理方式
- 小结

1. 引言
使用数据库集成Spring Security的目的和好处
-
数据库作为存储用户信息的可靠源:将用户信息存储在数据库中可以保证其持久性和安全性,并且可方便地进行管理和维护。
-
灵活的用户认证和授权配置:通过数据库集成,可以实现对不同用户的不同认证和授权方式,例如基于角色的访问控制或基于权限的细粒度控制。
-
可拓展性和可定制化:通过数据库集成,可以轻松地添加新的用户、角色和权限,并且能够根据具体需求进行自定义身份验证和授权逻辑的开发。
-
统一管理用户信息:通过数据库集成,可以实现统一管理用户信息。当用户信息发生变化时,例如更改密码、添加或删除角色等,只需在数据库中进行修改即可。
在本文中,我们将深入探讨如何将Spring Security与数据库集成,实现基于数据库的用户身份验证和授权。我们将介绍Spring Security的基本概念和功能,讨论数据库设计和配置的具体细节,并提供完整的示例代码来演示这种集成方式的实际应用。通过阅读本文,读者将能够理解和应用这种集成方式,构建安全可靠的认证和授权系统。

2. 数据库设计与配置
在使用数据库进行身份验证和授权时,我们需要设计和配置适合存储用户信息和角色信息的数据库结构。这些信息通常存储在两张表中:用户表和角色表。
2.1 用户表的结构和字段
用户表通常包含以下字段:
id: 用户的唯一标识符username: 用户名password: 经过加密的密码enabled: 标识用户是否启用(例如,激活状态)- 其他可选字段,如
email、phone等
以下是一个示例用户表的SQL定义:
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(64) NOT NULL,password VARCHAR(256) NOT NULL,enabled BOOLEAN NOT NULL,email VARCHAR(128),phone VARCHAR(16)
);
2.2 角色表的结构和字段
角色表用于定义不同用户角色,并且与用户表之间存在关联。角色表通常包含以下字段:
id: 角色的唯一标识符name: 角色名称
以下是一个示例角色表的SQL定义:
CREATE TABLE roles (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(64) NOT NULL
);
2.3 配置Spring Security与数据库的连接
在Spring Security中配置与数据库的连接,需要提供数据库的连接信息、用户名、密码等配置。我们可以使用Spring的配置文件(如application.properties)或Java配置类来配置数据库连接。
以下是一个示例的application.properties文件配置数据库连接:
spring.datasource.url=jdbc:mysql://localhost:3306/security_db
spring.datasource.username=db_username
spring.datasource.password=db_password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
在Spring Security配置中,我们需要配置一个UserDetailsService,它负责从数据库中加载用户信息并提供给Spring Security进行身份验证和授权。
以下是一个示例的Java配置类示例,其中配置了UserDetailsService:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?").authoritiesByUsernameQuery("SELECT u.username, r.name FROM users u, roles r, user_roles ur WHERE u.id = ur.user_id AND r.id = ur.role_id AND u.username = ?");}// Other security configurations...
}
在上述示例中,我们通过dataSource注入配置的数据库连接。usersByUsernameQuery和authoritiesByUsernameQuery用于自定义查询用户信息和角色/权限的SQL语句。
通过以上的数据库设计和配置,我们可以建立一个与Spring
Security集成的数据库,以存储用户和角色信息,并通过配置文件或Java配置类与Spring
Security建立连接。这将为我们的身份验证和授权提供基础。
3. 用户认证
用户认证是确保用户身份有效性的过程。在基于数据库的用户认证中,我们将使用Spring Security来实现用户认证功能。
3.1 实现基于数据库的用户认证功能
通过配置UserDetailsService,我们可以从数据库中加载用户信息,并将其与用户提交的凭据进行比较以验证其身份。
以下是一个示例的UserDetailsService实现类,用于从数据库中加载用户信息:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userRepository.findByUsername(username);if (user == null) {throw new UsernameNotFoundException("User not found");}return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),user.getAuthorities());}
}
在上述示例中,我们注入了UserRepository,该接口用于查询数据库中的用户信息。
3.2 使用Spring Security的Encoder进行密码加密和验证
为了保护用户密码的安全性,我们需要对密码进行加密并进行比较。Spring Security提供了多种加密方式,例如BCrypt、SHA-256等。
以下是一个示例的密码加密和验证示例:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder);}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// Other security configurations...
}
在上述示例中,我们配置了一个PasswordEncoder bean,并将其注入到AuthenticationManagerBuilder中。这样,当用户登录时,Spring Security会自动将用户输入的密码与数据库中存储的加密密码进行比较。
4.3 自定义用户认证的逻辑和处理方式
通过实现UserDetailsService接口和使用PasswordEncoder,我们可以实现基于数据库的用户认证。但有时我们可能需要自定义用户认证的逻辑和处理方式。
以下是一个示例的自定义用户认证的配置示例:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(customAuthenticationProvider());}@Beanpublic AuthenticationProvider customAuthenticationProvider() {CustomAuthenticationProvider authenticationProvider = new CustomAuthenticationProvider();authenticationProvider.setUserDetailsService(userDetailsService);authenticationProvider.setPasswordEncoder(passwordEncoder());return authenticationProvider;}// Other security configurations...
}
在上述示例中,我们实现自定义的CustomAuthenticationProvider,并将其注册为AuthenticationProvider。CustomAuthenticationProvider可以实现自定义的用户认证逻辑,例如通过额外的验证步骤、读取其他系统的用户信息等。
以下是一个示例的CustomAuthenticationProvider类:
public class CustomAuthenticationProvider implements AuthenticationProvider {private UserDetailsService userDetailsService;private PasswordEncoder passwordEncoder;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {String username = authentication.getName();String password = authentication.getCredentials().toString();UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (passwordEncoder.matches(password, userDetails.getPassword())) {return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());} else {throw new BadCredentialsException("Invalid credentials");}}@Overridepublic boolean supports(Class<?> authentication) {return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);}// Setter methods for UserDetailsService and PasswordEncoder
}
在上述示例中,我们通过UserDetailsService加载用户信息,并使用PasswordEncoder验证密码。如果用户认证通过,我们创建一个UsernamePasswordAuthenticationToken对象来表示成功的认证。
通过自定义用户认证逻辑和处理方式,我们可以灵活地应对各种特定的认证需求,如双因素身份验证、第三方认证等。
通过以上的实现和配置,我们可以实现基于数据库的用户认证。Spring Security将会验证用户提交的凭证,并根据数据库中的用户信息进行身份验证。为了保障密码的安全性,我们可以使用SpringSecurity提供的加密方式对密码进行加密和验证。同时,如果需要自定义用户认证逻辑和处理方式,我们可以实现自己的
CustomAuthenticationProvider来满足特定的需求。
4. 用户授权
用户授权是为了确定用户能够访问系统中特定资源的权限。在基于数据库的用户授权功能中,我们将使用数据库中定义的角色和权限进行授权操作。
4.1 基于数据库的用户授权功能
通过配置Spring Security,我们可以使用数据库中定义的角色和权限对用户进行授权。
以下是一个示例的权限验证规则和授权方式的配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasAnyRole("ADMIN", "USER").anyRequest().authenticated().and().formLogin().and().logout();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}// Other security configurations...
}
在上述示例中,我们通过antMatchers定义了不同URL路径的权限验证规则。例如,"/admin/“路径需要具有"ADMIN"角色才能访问,而”/user/"路径需要具有"ADMIN"或"USER"角色才能访问。
4.2 在数据库中定义角色和权限
为了实现基于数据库的用户授权功能,我们需要在数据库中定义角色和权限。
以下是一个示例的角色表和权限表的定义:
CREATE TABLE roles (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(64) NOT NULL
);CREATE TABLE permissions (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(64) NOT NULL
);
然后,我们需要定义用户与角色之间的关联,以及角色与权限之间的关联。
以下是一个示例的用户角色关联表和角色权限关联表的定义:
CREATE TABLE user_roles (user_id INT NOT NULL,role_id INT NOT NULL,PRIMARY KEY (user_id, role_id),FOREIGN KEY (user_id) REFERENCES users(id),FOREIGN KEY (role_id) REFERENCES roles(id)
);CREATE TABLE role_permissions (role_id INT NOT NULL,permission_id INT NOT NULL,PRIMARY KEY (role_id, permission_id),FOREIGN KEY (role_id) REFERENCES roles(id),FOREIGN KEY (permission_id) REFERENCES permissions(id)
);
通过以上的数据库定义,我们可以在数据库中建立用户、角色和权限的关联关系,并在用户授权时使用。
4.3 配置权限验证规则和授权方式
在上述的Spring Security配置中,我们使用antMatchers定义了访问路径的权限验证规则,并指定了需要具有哪些角色才能访问对应的路径。
除了使用角色进行访问控制外,我们也可以使用权限进行访问控制。权限是角色的组成部分,每个角色可以具有多个权限。
以下是一个示例的权限验证规则和授权方式的配置,基于数据库中的角色和权限:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasAuthority("ADMIN_ACCESS").antMatchers("/user/**").hasAnyAuthority("ADMIN_ACCESS", "USER_ACCESS").anyRequest().authenticated().and().formLogin().and().logout();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}// Other security configurations...
}
在上述示例中,我们使用hasAuthority和hasAnyAuthority来配置权限验证规则。例如,"/admin/“路径需要具有"ADMIN_ACCESS"权限才能访问,而”/user/"路径需要具有"ADMIN_ACCESS"或"USER_ACCESS"权限才能访问。
4.4 自定义用户授权的逻辑和处理方式
通过自定义UserDetailsService和AuthenticationProvider,我们可以实现自定义的用户授权逻辑和处理方式。
例如,在UserDetailsService中,我们可以根据具体的业务逻辑从数据库中加载用户信息和授权信息。在AuthenticationProvider中,我们可以实现自定义的授权逻辑,例如根据用户的其他属性进行额外的授权判断。
通过自定义用户授权的逻辑和处理方式,我们可以灵活地定义和调整系统中的权限控制方式,以满足不同的业务需求。
小结
这篇文章的主要目标是展示如何将Spring Security与数据库集成,实现基于数据库的用户身份认证和授权。通过引入数据库,并配合Spring Security的功能和配置,可以构建一个安全可靠的用户认证和授权系统

相关文章:
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…...
mysql8查看执行sql记录历史,配置开启sql历史日志general_log
1.概要说明 mysql8默认未开启sql记录历史日志。 2.配置开启general_log 2.1.查看配置 general_log:是否开启sql日志。默认为OFFlog_output:日志输出位置: FILE:输出到文件。默认值TABLE:输出到表。mysql.general_log show v…...
git 版本控制与合并
一 git概述: - Git是一种分布式版本控制系统,用于跟踪和管理软件开发项目中的代码变更。 - 它允许多人协同工作,记录代码历史变更,并轻松管理多个项目版本。 **Git的主要特点**包括: 1. **分布式系统**:…...
【力扣】23. 合并 K 个升序链表 <链表指针、堆排序、分治>
目录 【力扣】23. 合并 K 个升序链表题解方法一:暴力,先遍历取出来值到数组中排序,再生成新链表方法二:基础堆排序(使用优先队列 PriorityQueue)方法三:基础堆排序(使用优先队列 Pri…...
微信小程序真机防盗链referer问题处理
公司使用百度云存储一些资源,然后现在要做防盗链,在CDN加入Referer白名单后发现PC是正常的,微信小程序无法正常访问资源了。然后是各种查啊,然后发现是微信小程序不支持Referer的修改,且在小程序开发工具是Referer是固…...
SpringBoot集成Redisson实现延迟队列
一、场景 1、下单未支付,超过10分钟取消订单 2、货到后7天未评价,自动好评 二、实现方案 1、使用xxl-job 定时任务按时检测,实时性不高 2、使用RabitMQ的插件rabbitmq_delayed_message_exchange插件 3、 redis的过期检测 redis.conf 中…...
思想道德与法治
1【单选题】公民的基本权利是指宪法规定的公民享有的基本的、必不可少的权利。公民的基本权利有不同的类别,公民的通信自由和通信秘密属于 A、人身自由 B、经济社会权利 C、政治权利和自由 D、教育科学文化权利 您的答案:A 参考答案:A 查…...
vue3登录页面
使用了element-plus <template><div class"login-wrapper"><!-- 背景图或者视频 --><div class"background" style"width: 100%; height: 100%; position: absolute; top: 0px; left: 0px;overflow: hidden;z-index:50;&qu…...
SK5代理与IP代理:网络安全守护者的双重防线
一、IP代理与SK5代理简介 IP代理: IP代理是一种通过中间服务器转发网络请求的技术。客户端向代理服务器发出请求,代理服务器将请求转发至目标服务器,并将目标服务器的响应返回给客户端。IP代理的主要功能是隐藏用户的真实IP地址,提…...
线程间的同步、如何解决线程冲突与死锁
一、线程同步概念: 线程同步是指在多线程编程中,为了保证多个线程之间的数据访问和操作的有序性以及正确性,需要采取一些机制来协调它们的执行。在多线程环境下,由于线程之间是并发执行的,可能会出现竞争条件…...
8.4一日总结
1.远程仓库的提交方式(免密提交) a.ssh:隧道加密传输协议,一般用来登录远程服务器 b.使用 git clone 仓库名 配置(生成公私钥对) ssh-Keygen [-t rsa -C 邮箱地址] 通过执行上述命令,全程回车,就会在~/.ssh/id_rsa(私钥)和id_rsa.pub(公钥),私钥是必须要保存好的,并不能…...
【面试】某公司记录一次面试题
文章目录 框架类1. Spring boot与 spring 架相比,好在哪里?2. Spring boot以及 Spring MVC 常用注解(如requestingMapping,responseBody 等)3. 常用的java 设计模式,spring 中用到哪些设计模式4. SpringIOC是什么,如何理解5. AOP…...
215. 数组中的第K个最大元素(快排+大根堆+小根堆)
题目链接:力扣 解题思路: 方法一:基于快速排序 因为题目中只需要找到第k大的元素,而快速排序中,每一趟排序都可以确定一个最终元素的位置。 当使用快速排序对数组进行降序排序时,那么如果有一趟排序过程…...
Ubuntu18.04配置ZED_SDK 4.0, 安装Nvidia显卡驱动、cuda12.1
卸载错误的显卡驱动、cuda 首先卸载nvidia相关的、卸载cuda sudo apt-get purge nvidia* sudo apt-get autoremove sudo apt-get remove --auto remove nvidia-cuda-toolkit sudo apt-get purge nvidia-cuda-toolkit 官方卸载cuda的方法: sudo apt-get --purge re…...
张量Tensor 深度学习
1 张量的定义 张量tensor理论是数学的一个分支学科,在力学中有重要的应用。张量这一术语源于力学,最初是用来表示弹性介质中各点应力状态的,后来张量理论发展成为力学和物理学的一个有力数学工具。 张量(Tensor)是一个…...
用Rust实现23种设计模式之桥接模式
桥接模式的优点: 桥接模式的设计目标是将抽象部分和实现部分分离,使它们可以独立变化。这种分离有以下几个优点: 解耦和灵活性:桥接模式可以将抽象部分和实现部分解耦,使它们可以独立地变化。这样,对于抽象…...
扩散模型实战(一):基本原理介绍
扩散模型(Diffusion Model)是⼀类⼗分先进的基于物理热⼒学中的扩散思想的深度学习⽣成模型,主要包括前向扩散和反向扩散两个过程。⽣成模型除了扩散模型之外,还有出现较早的VAE(Variational Auto-Encoder,…...
解决npm ERR! code ERESOLVE -npm ERR! ERESOLVE could not resolve
当使用一份vue源码开发项目时,npm install 报错了 npm ERR! code ERESOLVEnpm ERR! ERESOLVE could not resolvenpm ERR!npm ERR! While resolving: vue-admin-template4.4.0npm ERR! Found: webpack4.46.0npm ERR! node_modules/webpacknpm ERR! webpack"^4.0…...
HttpServletRequest和HttpServletResponse的获取与使用
相关笔记:【JavaWeb之Servlet】 文章目录 1、Servlet复习2、HttpServletRequest的使用3、HttpServletResponse的使用4、获取HttpServletRequest和HttpServletResponse 1、Servlet复习 Servlet是JavaWeb的三大组件之一: ServletFilter 过滤器Listener 监…...
css在线代码生成器
这里收集了许多有意思的css效果在线代码生成器适合每一位前端开发者 布局,效果类: 网格生成器https://cssgrid-generator.netlify.app/ CSS Grid Generator可帮助开发人员使用CSS Grid创建复杂的网格布局。网格布局是创建Web页面的灵活和响应式设计的强…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

